VSU works now
This commit is contained in:
		
							parent
							
								
									0a57ef0faf
								
							
						
					
					
						commit
						c06da32321
					
				| 
						 | 
				
			
			@ -64,8 +64,7 @@ typedef struct {
 | 
			
		|||
    } wave;
 | 
			
		||||
 | 
			
		||||
    /* Other state */
 | 
			
		||||
    uint32_t clocks;    /* Clocks until next sample */
 | 
			
		||||
    uint16_t output[2]; /* Current output sample */
 | 
			
		||||
    uint32_t clocks; /* Clocks until next sample */
 | 
			
		||||
} Channel;
 | 
			
		||||
 | 
			
		||||
/* Simulation state */
 | 
			
		||||
| 
						 | 
				
			
			@ -297,7 +296,7 @@ struct VB {
 | 
			
		|||
            float    o1[2];    /* Previous analog output sample */
 | 
			
		||||
            uint32_t capacity; /* Number of audio frames in samples */
 | 
			
		||||
            uint32_t offset;   /* Position in output buffer */
 | 
			
		||||
            int16_t *samples; /* Output memory */
 | 
			
		||||
            int16_t *samples;  /* Output memory */
 | 
			
		||||
        } out;
 | 
			
		||||
 | 
			
		||||
        /* Memory */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								core/vip.c
								
								
								
								
							
							
						
						
									
										16
									
								
								core/vip.c
								
								
								
								
							| 
						 | 
				
			
			@ -40,6 +40,18 @@ static const uint8_t BG_TEMPLATES[][64] = {
 | 
			
		|||
      6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* 8-bit color magnitude by brightness level */
 | 
			
		||||
static const uint8_t BRIGHT8[] = {
 | 
			
		||||
      0, 10, 16, 21, 25, 30, 33, 37, 40, 44, 47, 50, 53, 56, 59, 61,
 | 
			
		||||
     64, 67, 69, 72, 74, 77, 79, 82, 84, 86, 89, 91, 93, 95, 97,100,
 | 
			
		||||
    102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,131,
 | 
			
		||||
    133,135,137,139,141,142,144,146,148,149,151,153,155,156,158,160,
 | 
			
		||||
    161,163,165,166,168,170,171,173,175,176,178,179,181,183,184,186,
 | 
			
		||||
    187,189,190,192,194,195,197,198,200,201,203,204,206,207,209,210,
 | 
			
		||||
    212,213,215,216,217,219,220,222,223,225,226,227,229,230,232,233,
 | 
			
		||||
    235,236,237,239,240,241,243,244,246,247,248,250,251,252,254,255
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***************************** Module Functions ******************************/
 | 
			
		||||
| 
						 | 
				
			
			@ -392,9 +404,9 @@ static void vipComputeBrightness(VB *sim) {
 | 
			
		|||
    brt[2] = repeat * sim->vip.brtRest[1];
 | 
			
		||||
    brt[3] = repeat * sim->vip.brtRest[2] + brt[2] + brt[1];
 | 
			
		||||
 | 
			
		||||
    /* Scale brightness values to 0..255 */
 | 
			
		||||
    /* Transform brightness values to 0..255 */
 | 
			
		||||
    for (x = 1; x < 4; x++)
 | 
			
		||||
        sim->vip.dp.brt[x] = ((brt[x] > 127 ? 127 : brt[x]) * 510 + 127) / 254;
 | 
			
		||||
        sim->vip.dp.brt[x] = brt[x] > 127 ? 255 : BRIGHT8[brt[x]];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Transfer one column of frame buffer pixels to output */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										116
									
								
								core/vsu.c
								
								
								
								
							
							
						
						
									
										116
									
								
								core/vsu.c
								
								
								
								
							| 
						 | 
				
			
			@ -5,7 +5,7 @@
 | 
			
		|||
 | 
			
		||||
/********************************* Constants *********************************/
 | 
			
		||||
 | 
			
		||||
/* Analog output low-pass filter coefficient = 0.022 / (0.022 + 1 / 41700) */
 | 
			
		||||
/* Analog output high-pass filter coefficient = 0.022 / (0.022 + 1 / 41700) */
 | 
			
		||||
#define RC_A (float) (1 - 1 / 918.4)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ static void vsuOnSamples(VB *sim) {
 | 
			
		|||
    if (sim->onSamples != NULL)
 | 
			
		||||
        VB_ON_SAMPLES(sim, sim->vsu.out.samples, sim->vsu.out.capacity);
 | 
			
		||||
}
 | 
			
		||||
#undef VB_ON_EXCEPTION
 | 
			
		||||
#undef VB_ON_SAMPLES
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -78,29 +78,11 @@ static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) {
 | 
			
		|||
    uint32_t bit;     /* Pseudorandom bit */
 | 
			
		||||
    Channel *chan;    /* Channel handle */
 | 
			
		||||
    int      freqmod; /* Frequency modifications enabled */
 | 
			
		||||
    uint32_t level;   /* Stereo output level */
 | 
			
		||||
    uint32_t sample;  /* Input sample */
 | 
			
		||||
    uint32_t until;   /* Clocks to process sub-channel components */
 | 
			
		||||
    int      e;       /* Iterator */
 | 
			
		||||
 | 
			
		||||
    /* Select channel */
 | 
			
		||||
    chan = &sim->vsu.channels[index];
 | 
			
		||||
 | 
			
		||||
    /* Select input sample */
 | 
			
		||||
    sample =
 | 
			
		||||
        !chan->int_.enb     ? 0 :                              /* Disabled */
 | 
			
		||||
        index == 5 ? (sim->vsu.noise.register_ & 1) ? 63 : 0 : /* Noise */
 | 
			
		||||
        chan->wave.wave > 4 ? 0 :                              /* Wave range */
 | 
			
		||||
        sim->vsu.waves[chan->wave.wave][chan->wave.sample]     /* Wave */
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    /* Compute output samples */
 | 
			
		||||
    for (e = 0; e < 2; e++) {
 | 
			
		||||
        level = e == 0 ? chan->lrv.left : chan->lrv.right;
 | 
			
		||||
        level = (level * chan->env.value >> 3) + (level && chan->env.value);
 | 
			
		||||
        chan->output[e] = level * sample;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Channel is disabled */
 | 
			
		||||
    if (!chan->int_.enb)
 | 
			
		||||
        return;
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +129,7 @@ static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) {
 | 
			
		|||
 | 
			
		||||
            /* Wave */
 | 
			
		||||
            if (index != 5) {
 | 
			
		||||
                chan->clocks = 4 * (2048 - (uint32_t) chan->freq.current);
 | 
			
		||||
                chan->clocks =  4 * (2048 - (uint32_t) chan->freq.current);
 | 
			
		||||
                chan->wave.sample = (chan->wave.sample + 1) & 31;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -157,7 +139,7 @@ static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) {
 | 
			
		|||
                bit = ((
 | 
			
		||||
                    sim->vsu.noise.register_ >> NOISE_TAPS[sim->vsu.noise.tap]^
 | 
			
		||||
                    sim->vsu.noise.register_ >> 7
 | 
			
		||||
                 ) & 1) ^ 1;
 | 
			
		||||
                ) & 1) ^ 1;
 | 
			
		||||
                sim->vsu.noise.register_ = bit |
 | 
			
		||||
                    (sim->vsu.noise.register_ << 1 & 0x7FFE);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -172,7 +154,6 @@ static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) {
 | 
			
		|||
                chan->env.value++;
 | 
			
		||||
            else if (chan->env.rep)
 | 
			
		||||
                chan->env.value = chan->env.reload;
 | 
			
		||||
            else chan->env.enb = 0;
 | 
			
		||||
            chan->env.clocks = ((uint32_t) chan->env.interval + 1) * 307220;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -190,6 +171,33 @@ static void vsuEmulateChannel(VB *sim, int index, uint32_t clocks) {
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Produce output for a channel */
 | 
			
		||||
static void vsuOutputChannel(VB *sim, int index, uint16_t *output) {
 | 
			
		||||
    Channel *chan;   /* Channel handle */
 | 
			
		||||
    uint32_t level;  /* Stereo output level */
 | 
			
		||||
    uint32_t sample; /* Input sample */
 | 
			
		||||
    int      e;      /* Iterator */
 | 
			
		||||
 | 
			
		||||
    /* Select channel */
 | 
			
		||||
    chan = &sim->vsu.channels[index];
 | 
			
		||||
 | 
			
		||||
    /* Select input sample */
 | 
			
		||||
    sample =
 | 
			
		||||
        !chan->int_.enb     ? 0 :                              /* Disabled */
 | 
			
		||||
        index == 5 ? (sim->vsu.noise.register_ & 1) ? 63 : 0 : /* Noise */
 | 
			
		||||
        chan->wave.wave > 4 ? 0 :                              /* Wave range */
 | 
			
		||||
        sim->vsu.waves[chan->wave.wave][chan->wave.sample]     /* Wave */
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    /* Compute output samples */
 | 
			
		||||
    for (e = 0; e < 2; e++) {
 | 
			
		||||
        level = e == 0 ? chan->lrv.left : chan->lrv.right;
 | 
			
		||||
        level = (level * chan->env.value >> 3) + (level && chan->env.value);
 | 
			
		||||
        output[e] += level * sample;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Write a value to S*EV0 */
 | 
			
		||||
static void vsuWriteEV0(VB *sim, int index, uint8_t value) {
 | 
			
		||||
    Channel *chan = &sim->vsu.channels[index];
 | 
			
		||||
| 
						 | 
				
			
			@ -201,7 +209,7 @@ static void vsuWriteEV0(VB *sim, int index, uint8_t value) {
 | 
			
		|||
    chan->env.reload   = chan->env.value;
 | 
			
		||||
 | 
			
		||||
    /* Configure state */
 | 
			
		||||
    chan->env.clocks = (uint32_t) chan->env.interval * 307220;
 | 
			
		||||
    chan->env.clocks = 307220 * ((uint32_t) chan->env.interval + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Write a value to S*EV1 */
 | 
			
		||||
| 
						 | 
				
			
			@ -254,12 +262,16 @@ static void vsuWriteINT(VB *sim, int index, uint8_t value) {
 | 
			
		|||
    chan->int_.interval = value      & 31;
 | 
			
		||||
 | 
			
		||||
    /* Update state */
 | 
			
		||||
    chan->int_.clocks = 76805 * (uint32_t) chan->int_.interval;
 | 
			
		||||
    chan->clocks      = (index == 5 ? 40 : 4) *
 | 
			
		||||
        ((uint32_t) 2048 - chan->freq.current);
 | 
			
		||||
    if (index != 5)
 | 
			
		||||
    chan->int_.clocks = 76805 * ((uint32_t) chan->int_.interval + 1);
 | 
			
		||||
    if (chan->env.enb)
 | 
			
		||||
        chan->env.clocks = 307220 * ((uint32_t) chan->env.interval + 1);
 | 
			
		||||
    if (index != 5) {
 | 
			
		||||
        chan->wave.sample = 0;
 | 
			
		||||
    else sim->vsu.noise.register_ = 0x0000;
 | 
			
		||||
        chan->clocks =  4 * (2048 - (uint32_t) chan->freq.current);
 | 
			
		||||
    } else {
 | 
			
		||||
        sim->vsu.noise.register_ = 0x0000;
 | 
			
		||||
        chan->clocks = 40 * (2048 - (uint32_t) chan->freq.current);
 | 
			
		||||
    }
 | 
			
		||||
    if (index == 4) {
 | 
			
		||||
        sim->vsu.freqmod.clocks = (uint32_t) sim->vsu.freqmod.interval *
 | 
			
		||||
            (sim->vsu.freqmod.clk ? 153610 : 19201);
 | 
			
		||||
| 
						 | 
				
			
			@ -303,12 +315,11 @@ static void vsuWriteSWP(VB *sim, uint8_t value) {
 | 
			
		|||
 | 
			
		||||
/* Process component */
 | 
			
		||||
static void vsuEmulate(VB *sim, uint32_t clocks) {
 | 
			
		||||
    Channel *chan;       /* Channel handle */
 | 
			
		||||
    uint32_t digital[2]; /* Digital output samples */
 | 
			
		||||
    float    i0;         /* Current analog input sample */
 | 
			
		||||
    float    o0;         /* Current analog output sample */
 | 
			
		||||
    uint32_t until;      /* Clocks to process channels */
 | 
			
		||||
    int      e, x;       /* Iterators */
 | 
			
		||||
    float    i0;        /* Current analog input sample */
 | 
			
		||||
    float    o0;        /* Current analog output sample */
 | 
			
		||||
    uint16_t output[2]; /* Digital output samples */
 | 
			
		||||
    uint32_t until;     /* Clocks to process channels */
 | 
			
		||||
    int      e, x;      /* Iterators */
 | 
			
		||||
 | 
			
		||||
    /* Process all clocks */
 | 
			
		||||
    do {
 | 
			
		||||
| 
						 | 
				
			
			@ -318,23 +329,28 @@ static void vsuEmulate(VB *sim, uint32_t clocks) {
 | 
			
		|||
        if (sim->vsu.clocks < until)
 | 
			
		||||
            until = sim->vsu.clocks;
 | 
			
		||||
 | 
			
		||||
        /* Working variables */
 | 
			
		||||
        clocks    -= until;
 | 
			
		||||
        digital[0] = digital[1] = 0;
 | 
			
		||||
        /* Manage clocks */
 | 
			
		||||
        clocks          -= until;
 | 
			
		||||
        sim->vsu.clocks -= until;
 | 
			
		||||
 | 
			
		||||
        /* Process all channels */
 | 
			
		||||
        for (x = 0; x < 6; x++) {
 | 
			
		||||
            chan = &sim->vsu.channels[x];
 | 
			
		||||
        for (x = 0; x < 6; x++)
 | 
			
		||||
            vsuEmulateChannel(sim, x, until);
 | 
			
		||||
            digital[0] += chan->output[0];
 | 
			
		||||
            digital[1] += chan->output[1];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Wait for the current sample to finish */
 | 
			
		||||
        if (sim->vsu.clocks != 0)
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        /* Compute the output sample */
 | 
			
		||||
        output[0] = output[1] = 0;
 | 
			
		||||
        for (x = 0; x < 6; x++)
 | 
			
		||||
            vsuOutputChannel(sim, x, output);
 | 
			
		||||
 | 
			
		||||
        /* Output sample */
 | 
			
		||||
        for (e = 0; e < 2; e++) {
 | 
			
		||||
 | 
			
		||||
            /* Compute the output sample for this stereo channel */
 | 
			
		||||
            i0 = (digital[e] >> 4) / 685.0f;
 | 
			
		||||
            i0 = (output[e] >> 4) / 685.0f;
 | 
			
		||||
            o0 = RC_A * (sim->vsu.out.o1[e] + i0 - sim->vsu.out.i1[e]);
 | 
			
		||||
            if (o0 < -1.0f) o0 = -1.0f;
 | 
			
		||||
            if (o0 > +1.0f) o0 = +1.0f;
 | 
			
		||||
| 
						 | 
				
			
			@ -501,12 +517,12 @@ static void vsuWrite(VB*sim,uint32_t address,int type,int32_t value,int debug){
 | 
			
		|||
        case 0x518>>2: vsuWriteRAM(sim, 4, value); break; /* S5RAM */
 | 
			
		||||
        case 0x51C>>2: vsuWriteSWP(sim,    value); break; /* S5SWP */
 | 
			
		||||
 | 
			
		||||
        case 0x540>>2: vsuWriteINT(sim, 5, value); break; /* S5INT */
 | 
			
		||||
        case 0x544>>2: vsuWriteLRV(sim, 5, value); break; /* S5LRV */
 | 
			
		||||
        case 0x548>>2: vsuWriteFQL(sim, 5, value); break; /* S5FQL */
 | 
			
		||||
        case 0x54C>>2: vsuWriteFQH(sim, 5, value); break; /* S5FQH */
 | 
			
		||||
        case 0x550>>2: vsuWriteEV0(sim, 5, value); break; /* S5EV0 */
 | 
			
		||||
        case 0x554>>2: vsuWriteEV1(sim, 5, value); break; /* S5EV1 */
 | 
			
		||||
        case 0x540>>2: vsuWriteINT(sim, 5, value); break; /* S6INT */
 | 
			
		||||
        case 0x544>>2: vsuWriteLRV(sim, 5, value); break; /* S6LRV */
 | 
			
		||||
        case 0x548>>2: vsuWriteFQL(sim, 5, value); break; /* S6FQL */
 | 
			
		||||
        case 0x54C>>2: vsuWriteFQH(sim, 5, value); break; /* S6FQH */
 | 
			
		||||
        case 0x550>>2: vsuWriteEV0(sim, 5, value); break; /* S6EV0 */
 | 
			
		||||
        case 0x554>>2: vsuWriteEV1(sim, 5, value); break; /* S6EV1 */
 | 
			
		||||
 | 
			
		||||
        case 0x580>>2: /* SSTOP */
 | 
			
		||||
            if ((value & 1) == 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								makefile
								
								
								
								
							
							
						
						
									
										8
									
								
								makefile
								
								
								
								
							| 
						 | 
				
			
			@ -28,7 +28,8 @@ core:
 | 
			
		|||
        -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
 | 
			
		||||
        -D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
 | 
			
		||||
        -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
 | 
			
		||||
        -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
 | 
			
		||||
        -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_SAMPLES=testSamples \
 | 
			
		||||
        -D VB_DIRECT_READ=testRead
 | 
			
		||||
#	Clang generic
 | 
			
		||||
	@emcc core/vb.c -I core -c -o /dev/null -O3 \
 | 
			
		||||
        -Werror -std=c90 -Wall -Wextra -Wpedantic -fno-strict-aliasing
 | 
			
		||||
| 
						 | 
				
			
			@ -38,14 +39,15 @@ core:
 | 
			
		|||
        -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC \
 | 
			
		||||
        -D VB_DIRECT_EXCEPTION=textException -D VB_DIRECT_EXECUTE=textExecute \
 | 
			
		||||
        -D VB_DIRECT_FETCH=testFetch -D VB_DIRECT_FRAME=testFrame \
 | 
			
		||||
        -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_READ=testRead
 | 
			
		||||
        -D VB_DIRECT_WRITE=testWrite -D VB_DIRECT_SAMPLES=testSamples \
 | 
			
		||||
        -D VB_DIRECT_READ=testRead
 | 
			
		||||
 | 
			
		||||
.PHONY: wasm
 | 
			
		||||
wasm:
 | 
			
		||||
	@emcc -o web/core.wasm web/wasm.c core/vb.c -I core \
 | 
			
		||||
        -D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE \
 | 
			
		||||
        -D "VBAPI=__attribute__((used))" \
 | 
			
		||||
        --no-entry -O2 -flto -s WASM=1 \
 | 
			
		||||
        --no-entry -O2 -flto -s WASM=1 -s WARN_ON_UNDEFINED_SYMBOLS=0 \
 | 
			
		||||
        -s EXPORTED_RUNTIME_METHODS=[] -s ALLOW_MEMORY_GROWTH \
 | 
			
		||||
        -s MAXIMUM_MEMORY=4GB -fno-strict-aliasing
 | 
			
		||||
	@rm -f web/*.wasm.tmp*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue