From bcaf44c511efaad9d803dde9b0fdbb046498c66f Mon Sep 17 00:00:00 2001 From: João Silva Date: Sun, 18 Jun 2017 16:16:19 +0100 Subject: Support for savestate versioning. Plenty of cleanups. --- source/apu_blargg.h | 315 +++++++++++++++++++++++++--------------------------- 1 file changed, 152 insertions(+), 163 deletions(-) (limited to 'source/apu_blargg.h') diff --git a/source/apu_blargg.h b/source/apu_blargg.h index 00d9428..3a07e2c 100644 --- a/source/apu_blargg.h +++ b/source/apu_blargg.h @@ -9,20 +9,20 @@ typedef void (*dsp_copy_func_t)( uint8_t ** io, void* state, size_t ); -#define ECHO_HIST_SIZE 8 -#define ECHO_HIST_SIZE_X2 16 +#define ECHO_HIST_SIZE 8 +#define ECHO_HIST_SIZE_X2 16 /* Sound control */ /* Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). Reduces emulation accuracy. */ -#define VOICE_COUNT 8 -#define EXTRA_SIZE 16 -#define EXTRA_SIZE_DIV_2 8 -#define BRR_BUF_SIZE 12 -#define BRR_BUF_SIZE_X2 24 -#define BRR_BLOCK_SIZE 9 +#define VOICE_COUNT 8 +#define EXTRA_SIZE 16 +#define EXTRA_SIZE_DIV_2 8 +#define BRR_BUF_SIZE 12 +#define BRR_BUF_SIZE_X2 24 +#define BRR_BLOCK_SIZE 9 /* DSP register addresses */ @@ -32,176 +32,170 @@ typedef void (*dsp_copy_func_t)( uint8_t ** io, void* state, size_t ); #define R_MVOLR 0x1C #define R_EVOLL 0x2C #define R_EVOLR 0x3C -#define R_KON 0x4C -#define R_KOFF 0x5C -#define R_FLG 0x6C -#define R_ENDX 0x7C -#define R_EFB 0x0D -#define R_EON 0x4D -#define R_PMON 0x2D -#define R_NON 0x3D -#define R_DIR 0x5D -#define R_ESA 0x6D -#define R_EDL 0x7D -#define R_FIR 0x0F /* 8 coefficients at 0x0F, 0x1F ... 0x7F */ +#define R_KON 0x4C +#define R_KOFF 0x5C +#define R_FLG 0x6C +#define R_ENDX 0x7C +#define R_EFB 0x0D +#define R_EON 0x4D +#define R_PMON 0x2D +#define R_NON 0x3D +#define R_DIR 0x5D +#define R_ESA 0x6D +#define R_EDL 0x7D +#define R_FIR 0x0F /* 8 coefficients at 0x0F, 0x1F ... 0x7F */ /* Voice registers */ -#define V_VOLL 0x00 -#define V_VOLR 0x01 -#define V_PITCHL 0x02 -#define V_PITCHH 0x03 -#define V_SRCN 0x04 -#define V_ADSR0 0x05 -#define V_ADSR1 0x06 -#define V_GAIN 0x07 -#define V_ENVX 0x08 -#define V_OUTX 0x09 +#define V_VOLL 0x00 +#define V_VOLR 0x01 +#define V_PITCHL 0x02 +#define V_PITCHH 0x03 +#define V_SRCN 0x04 +#define V_ADSR0 0x05 +#define V_ADSR1 0x06 +#define V_GAIN 0x07 +#define V_ENVX 0x08 +#define V_OUTX 0x09 /* Status flag handling */ /* Hex value in name to clarify code and bit shifting. Flag stored in indicated variable during emulation */ -#define N80 0x80 /* nz */ -#define V40 0x40 /* psw */ -#define P20 0x20 /* dp */ -#define B10 0x10 /* psw */ -#define H08 0x08 /* psw */ -#define I04 0x04 /* psw */ -#define Z02 0x02 /* nz */ -#define C01 0x01 /* c */ +#define N80 0x80 /* nz */ +#define V40 0x40 /* psw */ +#define P20 0x20 /* dp */ +#define B10 0x10 /* psw */ +#define H08 0x08 /* psw */ +#define I04 0x04 /* psw */ +#define Z02 0x02 /* nz */ +#define C01 0x01 /* c */ #define NZ_NEG_MASK 0x880 /* either bit set indicates N flag set */ #define REGISTER_COUNT 128 -#define ENV_RELEASE 0 -#define ENV_ATTACK 1 -#define ENV_DECAY 2 -#define ENV_SUSTAIN 3 +#define ENV_RELEASE 0 +#define ENV_ATTACK 1 +#define ENV_DECAY 2 +#define ENV_SUSTAIN 3 typedef struct { - int32_t buf [BRR_BUF_SIZE_X2]; // decoded samples (twice the size to simplify wrap handling) - int32_t buf_pos; // place in buffer where next samples will be decoded - int32_t interp_pos; // relative fractional position in sample (0x1000 = 1.0) - int32_t brr_addr; // address of current BRR block - int32_t brr_offset; // current decoding offset in BRR block + int32_t buf [BRR_BUF_SIZE_X2]; // decoded samples (twice the size to simplify wrap handling) + int32_t buf_pos; // place in buffer where next samples will be decoded + int32_t interp_pos; // relative fractional position in sample (0x1000 = 1.0) + int32_t brr_addr; // address of current BRR block + int32_t brr_offset; // current decoding offset in BRR block uint8_t* regs; // pointer to voice's DSP registers - int32_t vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. - int32_t kon_delay; // KON delay/current setup phase - int32_t env_mode; - int32_t env; // current envelope level - int32_t hidden_env; // used by GAIN mode 7, very obscure quirk + int32_t vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. + int32_t kon_delay; // KON delay/current setup phase + int32_t env_mode; + int32_t env; // current envelope level + int32_t hidden_env; // used by GAIN mode 7, very obscure quirk uint8_t t_envx_out; } dsp_voice_t; typedef struct { - uint8_t regs [REGISTER_COUNT]; - - /* Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) */ - - int32_t echo_hist [ECHO_HIST_SIZE_X2] [2]; - - int32_t (*echo_hist_pos) [2]; /* &echo_hist [0 to 7] */ - - int32_t every_other_sample; /* toggles every sample */ - int32_t kon; /* KON value when last checked */ - int32_t noise; - int32_t counter; - int32_t echo_offset; /* offset from ESA in echo buffer */ - int32_t echo_length; /* number of bytes that echo_offset will stop at */ - int32_t phase; /* next clock cycle to run (0-31) */ + uint8_t regs [REGISTER_COUNT]; + int32_t echo_hist [ECHO_HIST_SIZE_X2] [2]; /* Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) */ + int32_t (*echo_hist_pos) [2]; /* &echo_hist [0 to 7] */ + int32_t every_other_sample; /* toggles every sample */ + int32_t kon; /* KON value when last checked */ + int32_t noise; + int32_t counter; + int32_t echo_offset; /* offset from ESA in echo buffer */ + int32_t echo_length; /* number of bytes that echo_offset will stop at */ + int32_t phase; /* next clock cycle to run (0-31) */ /* Hidden registers also written to when main register is written to */ - int32_t new_kon; - uint8_t endx_buf; - uint8_t envx_buf; - uint8_t outx_buf; - - /* Temporary state between clocks */ + int32_t new_kon; + uint8_t endx_buf; + uint8_t envx_buf; + uint8_t outx_buf; /* read once per sample */ - int32_t t_pmon; - int32_t t_non; - int32_t t_eon; - int32_t t_dir; - int32_t t_koff; + int32_t t_pmon; + int32_t t_non; + int32_t t_eon; + int32_t t_dir; + int32_t t_koff; /* read a few clocks ahead then used */ - int32_t t_brr_next_addr; - int32_t t_adsr0; - int32_t t_brr_header; - int32_t t_brr_byte; - int32_t t_srcn; - int32_t t_esa; - int32_t t_echo_enabled; + int32_t t_brr_next_addr; + int32_t t_adsr0; + int32_t t_brr_header; + int32_t t_brr_byte; + int32_t t_srcn; + int32_t t_esa; + int32_t t_echo_enabled; /* internal state that is recalculated every sample */ - int32_t t_dir_addr; - int32_t t_pitch; - int32_t t_output; - int32_t t_looped; - int32_t t_echo_ptr; + int32_t t_dir_addr; + int32_t t_pitch; + int32_t t_output; + int32_t t_looped; + int32_t t_echo_ptr; /* left/right sums */ - int32_t t_main_out [2]; - int32_t t_echo_out [2]; - int32_t t_echo_in [2]; + int32_t t_main_out [2]; + int32_t t_echo_out [2]; + int32_t t_echo_in [2]; - dsp_voice_t voices [VOICE_COUNT]; + dsp_voice_t voices [VOICE_COUNT]; /* non-emulation state */ - uint8_t* ram; /* 64K shared RAM between DSP and SMP */ - int16_t* out; - int16_t* out_end; - int16_t* out_begin; - int16_t extra [EXTRA_SIZE]; - - int32_t rom_enabled; - uint8_t* rom; - uint8_t* hi_ram; + uint8_t* ram; /* 64K shared RAM between DSP and SMP */ + int16_t* out; + int16_t* out_end; + int16_t* out_begin; + int16_t extra [EXTRA_SIZE]; + + int32_t rom_enabled; + uint8_t* rom; + uint8_t* hi_ram; } dsp_state_t; #if !SPC_NO_COPY_STATE_FUNCS -typedef struct { +typedef struct +{ dsp_copy_func_t func; - uint8_t** buf; + uint8_t** buf; } spc_state_copy_t; #define SPC_COPY( type, state ) state = (type) spc_copier_copy_int(&copier, state, sizeof (type) ); #endif -#define REG_COUNT 0x10 -#define PORT_COUNT 4 -#define TEMPO_UNIT 0x100 -#define STATE_SIZE 68 * 1024L /* maximum space needed when saving */ -#define TIMER_COUNT 3 -#define ROM_SIZE 0x40 -#define ROM_ADDR 0xFFC0 +#define REG_COUNT 0x10 +#define PORT_COUNT 4 +#define TEMPO_UNIT 0x100 +#define STATE_SIZE 68 * 1024L /* maximum space needed when saving */ +#define TIMER_COUNT 3 +#define ROM_SIZE 0x40 +#define ROM_ADDR 0xFFC0 /* 1024000 SPC clocks per second, sample pair every 32 clocks */ #define CLOCKS_PER_SAMPLE 32 -#define R_TEST 0x0 -#define R_CONTROL 0x1 -#define R_DSPADDR 0x2 -#define R_DSPDATA 0x3 -#define R_CPUIO0 0x4 -#define R_CPUIO1 0x5 -#define R_CPUIO2 0x6 -#define R_CPUIO3 0x7 -#define R_F8 0x8 -#define R_F9 0x9 -#define R_T0TARGET 0xA -#define R_T1TARGET 0xB -#define R_T2TARGET 0xC -#define R_T0OUT 0xD -#define R_T1OUT 0xE -#define R_T2OUT 0xF +#define R_TEST 0x0 +#define R_CONTROL 0x1 +#define R_DSPADDR 0x2 +#define R_DSPDATA 0x3 +#define R_CPUIO0 0x4 +#define R_CPUIO1 0x5 +#define R_CPUIO2 0x6 +#define R_CPUIO3 0x7 +#define R_F8 0x8 +#define R_F9 0x9 +#define R_T0TARGET 0xA +#define R_T1TARGET 0xB +#define R_T2TARGET 0xC +#define R_T0OUT 0xD +#define R_T1OUT 0xE +#define R_T2OUT 0xF /* Value that padding should be filled with */ #define CPU_PAD_FILL 0xFF @@ -230,9 +224,8 @@ uint8_t* spc_apuram(); typedef struct { - Timer timers [TIMER_COUNT]; - - uint8_t smp_regs [2] [REG_COUNT]; + Timer timers [TIMER_COUNT]; + uint8_t smp_regs [2] [REG_COUNT]; struct { @@ -244,27 +237,24 @@ typedef struct int32_t sp; } cpu_regs; - int32_t dsp_time; - int32_t spc_time; - - int32_t tempo; - + int32_t dsp_time; + int32_t spc_time; + int32_t tempo; int32_t extra_clocks; int16_t* buf_begin; - int16_t* buf_end; + int16_t* buf_end; int16_t* extra_pos; - int16_t extra_buf [EXTRA_SIZE]; - - int32_t rom_enabled; - uint8_t rom [ROM_SIZE]; - uint8_t hi_ram [ROM_SIZE]; - - uint8_t cycle_table [256]; + int16_t extra_buf [EXTRA_SIZE]; + int32_t rom_enabled; + uint8_t rom [ROM_SIZE]; + uint8_t hi_ram [ROM_SIZE]; + uint8_t cycle_table [256]; struct { /* padding to neutralize address overflow */ - union { + union + { uint8_t padding1 [0x100]; uint16_t align; /* makes compiler align data for 16-bit access */ } padding1 [1]; @@ -280,28 +270,27 @@ typedef void (*apu_callback)(); #define SPC_SAVE_STATE_BLOCK_SIZE (STATE_SIZE + 8) -bool S9xInitAPU(); -void S9xDeinitAPU(); -void S9xResetAPU(); -void S9xSoftResetAPU(); +bool S9xInitAPU(); +void S9xDeinitAPU(); +void S9xResetAPU(); +void S9xSoftResetAPU(); uint8_t S9xAPUReadPort(int32_t port); -void S9xAPUWritePort(int32_t port, uint8_t byte); -void S9xAPUExecute(); -void S9xAPUSetReferenceTime(int32_t cpucycles); -void S9xAPUTimingSetSpeedup(int32_t ticks); -void S9xAPUAllowTimeOverflow(bool allow); -void S9xAPULoadState(const uint8_t * block); -void S9xAPUSaveState(uint8_t * block); +void S9xAPUWritePort(int32_t port, uint8_t byte); +void S9xAPUExecute(); +void S9xAPUSetReferenceTime(int32_t cpucycles); +void S9xAPUTimingSetSpeedup(int32_t ticks); +void S9xAPUAllowTimeOverflow(bool allow); +void S9xAPULoadState(const uint8_t * block); +void S9xAPUSaveState(uint8_t * block); -bool S9xInitSound(int32_t buffer_ms, int32_t lag_ms); +bool S9xInitSound(int32_t buffer_ms, int32_t lag_ms); -bool S9xSyncSound(); +bool S9xSyncSound(); int32_t S9xGetSampleCount(); -void S9xFinalizeSamples(); -void S9xClearSamples(); -bool S9xMixSamples(int16_t * buffer, uint32_t sample_count); -void S9xSetSamplesAvailableCallback(apu_callback); +void S9xFinalizeSamples(); +void S9xClearSamples(); +bool S9xMixSamples(int16_t * buffer, uint32_t sample_count); +void S9xSetSamplesAvailableCallback(apu_callback); #endif // APU_BLARGG_H - #endif -- cgit v1.2.3