Implement VSU
This commit is contained in:
@@ -11,6 +11,63 @@
|
||||
/* Output image */
|
||||
typedef uint8_t Pixels[2][384*224];
|
||||
|
||||
/* VSU channel */
|
||||
typedef struct {
|
||||
|
||||
/* Envelope */
|
||||
struct {
|
||||
|
||||
/* Register state */
|
||||
uint8_t enb; /* Modifications enabled */
|
||||
uint8_t dir; /* Modification direction */
|
||||
uint8_t interval; /* Modification interval */
|
||||
uint8_t rep; /* Repeat modifications */
|
||||
uint8_t value; /* Master output level */
|
||||
|
||||
/* Other state */
|
||||
uint32_t clocks; /* Clocks until modification */
|
||||
uint8_t reload; /* Automatic reload value */
|
||||
} env;
|
||||
|
||||
/* Frequency */
|
||||
struct {
|
||||
uint16_t current; /* Current value */
|
||||
uint16_t written; /* Last value written */
|
||||
} freq;
|
||||
|
||||
/* Stereo levels */
|
||||
struct {
|
||||
uint8_t left; /* Left output level */
|
||||
uint8_t right; /* Right output level */
|
||||
} lrv;
|
||||
|
||||
/* Control */
|
||||
struct {
|
||||
|
||||
/* Register state */
|
||||
uint8_t auto_; /* Shutoff enabled */
|
||||
uint8_t enb; /* Sound generation enabled */
|
||||
uint8_t interval; /* Shutoff interval */
|
||||
|
||||
/* Other state */
|
||||
uint32_t clocks; /* Clocks until shutoff */
|
||||
} int_;
|
||||
|
||||
/* Waveform */
|
||||
struct {
|
||||
|
||||
/* Register state */
|
||||
uint8_t wave; /* Waveform index */
|
||||
|
||||
/* Other state */
|
||||
int sample; /* Current sample index */
|
||||
} wave;
|
||||
|
||||
/* Other state */
|
||||
uint32_t clocks; /* Clocks until next sample */
|
||||
uint16_t output[2]; /* Current output sample */
|
||||
} Channel;
|
||||
|
||||
/* Simulation state */
|
||||
struct VB {
|
||||
|
||||
@@ -93,7 +150,7 @@ struct VB {
|
||||
/* Game pad */
|
||||
struct {
|
||||
|
||||
/* Hardware state */
|
||||
/* Register state */
|
||||
uint8_t k_int_inh; /* Interrupt acknowledge/disable */
|
||||
uint8_t para_si; /* Read reset signal */
|
||||
uint8_t s_abt_dis; /* Abort hardware read */
|
||||
@@ -102,7 +159,7 @@ struct VB {
|
||||
uint32_t si_stat; /* Hardware read in progress */
|
||||
uint8_t soft_ck; /* Controller communication signal */
|
||||
|
||||
/* Simulation state */
|
||||
/* Other state */
|
||||
uint16_t keys; /* Next input bits */
|
||||
int step; /* Software read processing phase */
|
||||
} pad;
|
||||
@@ -110,13 +167,13 @@ struct VB {
|
||||
/* Timer */
|
||||
struct {
|
||||
|
||||
/* Hardware state */
|
||||
/* Register state */
|
||||
uint8_t t_clk_sel; /* Counter tick duration */
|
||||
uint8_t t_enb; /* Enable timer */
|
||||
uint8_t tim_z_int; /* Enable interrupt */
|
||||
uint8_t z_stat; /* Zero status */
|
||||
|
||||
/* Simulation state */
|
||||
/* Other state */
|
||||
uint32_t clocks; /* Master clocks to wait */
|
||||
uint16_t counter; /* Current counter value */
|
||||
uint16_t reload; /* Reload counter value */
|
||||
@@ -135,7 +192,7 @@ struct VB {
|
||||
/* Display processor */
|
||||
struct {
|
||||
|
||||
/* Hardware state */
|
||||
/* Register state */
|
||||
uint8_t disp; /* Display enabled */
|
||||
uint8_t fclk; /* Frame clock signal high */
|
||||
uint8_t l0bsy; /* Displaying left frame buffer 0 */
|
||||
@@ -147,7 +204,7 @@ struct VB {
|
||||
uint8_t scanrdy; /* Mirrors are stable */
|
||||
uint8_t synce; /* Servo enabled */
|
||||
|
||||
/* Simulation state */
|
||||
/* Other state */
|
||||
uint8_t brt[4]; /* Precomputed brightness */
|
||||
int buffer; /* Index of frame buffer to display */
|
||||
uint32_t clocks; /* Master clocks to wait */
|
||||
@@ -163,7 +220,7 @@ struct VB {
|
||||
/* Pixel processor */
|
||||
struct {
|
||||
|
||||
/* Hardware state */
|
||||
/* Register state */
|
||||
uint8_t f0bsy; /* Drawing into frame buffer 0 */
|
||||
uint8_t f1bsy; /* Drawing into frame buffer 1 */
|
||||
uint8_t overtime; /* Drawing extends into display interval */
|
||||
@@ -172,7 +229,7 @@ struct VB {
|
||||
uint32_t sbout; /* Drawing specified vertical output position */
|
||||
uint8_t xpen; /* Drawing enabled */
|
||||
|
||||
/* Simulation state */
|
||||
/* Other state */
|
||||
uint32_t clocks; /* Master clocks to wait */
|
||||
int column; /* Current horizontal output position */
|
||||
int frame; /* FRMCYC counter */
|
||||
@@ -200,6 +257,58 @@ struct VB {
|
||||
uint8_t ram[0x40000]; /* Video memory */
|
||||
} vip;
|
||||
|
||||
/* VSU */
|
||||
struct {
|
||||
|
||||
/* Audio sources */
|
||||
Channel channels[6];
|
||||
|
||||
/* Channel 5 frequency modification */
|
||||
struct {
|
||||
|
||||
/* Register state */
|
||||
uint8_t clk; /* Base modification clock */
|
||||
uint8_t dir; /* Sweep direction */
|
||||
uint8_t enb; /* Modifications enabled */
|
||||
uint8_t func; /* Modification function */
|
||||
uint8_t interval; /* Modification interval */
|
||||
uint8_t rep; /* Repeat modulation */
|
||||
uint8_t shift; /* Sweep shift amount */
|
||||
|
||||
/* Other state */
|
||||
uint32_t clocks; /* Clocks until modification */
|
||||
uint16_t next; /* Next frequency value */
|
||||
int sample; /* Current sample index */
|
||||
} freqmod;
|
||||
|
||||
/* Channel 6 noise generator */
|
||||
struct {
|
||||
|
||||
/* Register state */
|
||||
uint8_t tap; /* LSFR feedback bit position */
|
||||
|
||||
/* Other state */
|
||||
uint16_t register_; /* Pseudorandom bits */
|
||||
} noise;
|
||||
|
||||
/* Sample output */
|
||||
struct {
|
||||
float i1[2]; /* Previous analog input sample */
|
||||
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 */
|
||||
} out;
|
||||
|
||||
/* Memory */
|
||||
int8_t modulation[32]; /* Modulation amounts */
|
||||
uint8_t waves[5][32]; /* Wafeform samples */
|
||||
|
||||
/* Other state */
|
||||
uint32_t clocks; /* Clocks until next output sample */
|
||||
int sample; /* Output sample index, period 417 */
|
||||
} vsu;
|
||||
|
||||
/* Other state */
|
||||
uint8_t wcr; /* Wait controller state */
|
||||
uint8_t wram[0x10000]; /* System RAM */
|
||||
@@ -210,6 +319,7 @@ struct VB {
|
||||
vbOnFetch onFetch; /* CPU instruction fetch */
|
||||
vbOnFrame onFrame; /* VIP frame ready */
|
||||
vbOnRead onRead; /* CPU instruction read */
|
||||
vbOnSamples onSamples; /* VSU samples full */
|
||||
vbOnWrite onWrite; /* CPU instruction write */
|
||||
void *tag; /* User data */
|
||||
};
|
||||
@@ -238,6 +348,7 @@ static int32_t SignExtend(int32_t value, int32_t bits) {
|
||||
#include "bus.c"
|
||||
#include "cpu.c"
|
||||
#include "vip.c"
|
||||
#include "vsu.c"
|
||||
|
||||
|
||||
|
||||
@@ -245,20 +356,21 @@ static int32_t SignExtend(int32_t value, int32_t bits) {
|
||||
|
||||
/* Process a simulation for a given number of clocks */
|
||||
static int sysEmulate(VB *sim, uint32_t clocks) {
|
||||
return
|
||||
cpuEmulate(sim, clocks) |
|
||||
vipEmulate(sim, clocks) |
|
||||
padEmulate(sim, clocks) |
|
||||
tmrEmulate(sim, clocks)
|
||||
;
|
||||
int ret;
|
||||
ret = cpuEmulate(sim, clocks);
|
||||
padEmulate(sim, clocks);
|
||||
tmrEmulate(sim, clocks);
|
||||
vsuEmulate(sim, clocks);
|
||||
ret |= vipEmulate(sim, clocks);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Determine how many clocks are guaranteed to process */
|
||||
static uint32_t sysUntil(VB *sim, uint32_t clocks) {
|
||||
clocks = cpuUntil(sim, clocks);
|
||||
clocks = vipUntil(sim, clocks);
|
||||
clocks = padUntil(sim, clocks);
|
||||
clocks = tmrUntil(sim, clocks);
|
||||
clocks = vipUntil(sim, clocks);
|
||||
return clocks;
|
||||
}
|
||||
|
||||
@@ -395,6 +507,27 @@ VBAPI vbOnRead vbGetReadCallback(VB *sim) {
|
||||
return sim->onRead;
|
||||
}
|
||||
|
||||
/* Retrieve the audio samples buffer */
|
||||
VBAPI void* vbGetSamples(VB *sim, uint32_t *capacity, uint32_t *position) {
|
||||
if (capacity == NULL) {
|
||||
if (capacity != NULL)
|
||||
*capacity = 0;
|
||||
if (position != NULL)
|
||||
*position = 0;
|
||||
} else {
|
||||
if (capacity != NULL)
|
||||
*capacity = sim->vsu.out.capacity;
|
||||
if (position != NULL)
|
||||
*position = sim->vsu.out.offset >> 1;
|
||||
}
|
||||
return sim->vsu.out.samples;
|
||||
}
|
||||
|
||||
/* Retrieve the samples callback handler */
|
||||
VBAPI vbOnSamples vbGetSamplesCallback(VB *sim) {
|
||||
return sim->onSamples;
|
||||
}
|
||||
|
||||
/* Retrieve the value in a system register */
|
||||
VBAPI uint32_t vbGetSystemRegister(VB *sim, int index) {
|
||||
return index < 0 || index > 31 ? 0 : cpuGetSystemRegister(sim, index);
|
||||
@@ -412,13 +545,15 @@ VBAPI vbOnWrite vbGetWriteCallback(VB *sim) {
|
||||
|
||||
/* Initialize a simulation instance */
|
||||
VBAPI VB* vbInit(VB *sim) {
|
||||
sim->cart.ram = NULL;
|
||||
sim->cart.rom = NULL;
|
||||
sim->onExecute = NULL;
|
||||
sim->onFetch = NULL;
|
||||
sim->onFrame = NULL;
|
||||
sim->onRead = NULL;
|
||||
sim->onWrite = NULL;
|
||||
sim->cart.ram = NULL;
|
||||
sim->cart.rom = NULL;
|
||||
sim->vsu.out.samples = NULL;
|
||||
sim->onExecute = NULL;
|
||||
sim->onFetch = NULL;
|
||||
sim->onFrame = NULL;
|
||||
sim->onRead = NULL;
|
||||
sim->onSamples = NULL;
|
||||
sim->onWrite = NULL;
|
||||
vbReset(sim);
|
||||
return sim;
|
||||
}
|
||||
@@ -445,9 +580,10 @@ VBAPI VB* vbReset(VB *sim) {
|
||||
|
||||
/* Components */
|
||||
cpuReset(sim);
|
||||
vipReset(sim);
|
||||
padReset(sim);
|
||||
tmrReset(sim);
|
||||
vipReset(sim);
|
||||
vsuReset(sim);
|
||||
return sim;
|
||||
}
|
||||
|
||||
@@ -526,6 +662,23 @@ VBAPI vbOnRead vbSetReadCallback(VB *sim, vbOnRead callback) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* Specify a new audio samples buffer */
|
||||
VBAPI int vbSetSamples(VB *sim, void *samples, uint32_t capacity) {
|
||||
if (capacity == 0 || capacity > 0x40000000)
|
||||
return 1;
|
||||
sim->vsu.out.capacity = capacity;
|
||||
sim->vsu.out.offset = 0;
|
||||
sim->vsu.out.samples = samples;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Specify a new samples callback handler */
|
||||
VBAPI vbOnSamples vbSetSamplesCallback(VB *sim, vbOnSamples callback) {
|
||||
vbOnSamples prev = sim->onSamples;
|
||||
sim->onSamples = callback;
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* Specify a new value for a system register */
|
||||
VBAPI uint32_t vbSetSystemRegister(VB *sim, int index, uint32_t value) {
|
||||
return index < 0 || index > 31 ? 0 :
|
||||
|
||||
Reference in New Issue
Block a user