From 79cc82a59f56c63de8b3e058224911dd905862a1 Mon Sep 17 00:00:00 2001 From: spacy51 Date: Mon, 25 Aug 2008 22:02:15 +0000 Subject: [PATCH] FIXED GB audio state loading [blargg] --- src/dmg/GB.cpp | 8 ++- src/dmg/gbSound.cpp | 120 ++++++++++++++++++++++++++++++-------------- 2 files changed, 89 insertions(+), 39 deletions(-) diff --git a/src/dmg/GB.cpp b/src/dmg/GB.cpp index 67182c9a..dbb2d82b 100644 --- a/src/dmg/GB.cpp +++ b/src/dmg/GB.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "../System.h" #include "../NLS.h" @@ -591,7 +592,8 @@ u8 ZeroTable[256] = { #define GBSAVE_GAME_VERSION_9 9 #define GBSAVE_GAME_VERSION_10 10 #define GBSAVE_GAME_VERSION_11 11 -#define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_11 +#define GBSAVE_GAME_VERSION_12 12 +#define GBSAVE_GAME_VERSION GBSAVE_GAME_VERSION_12 int inline gbGetValue(int min,int max,int v) { @@ -3565,6 +3567,7 @@ static bool gbWriteSaveState(gzFile gzFile) utilWriteInt(gzFile, gbWindowLine); utilWriteInt(gzFile, inUseRegister_WY); utilWriteInt(gzFile, gbScreenOn); + utilWriteInt(gzFile, 0x12345678); // end marker return true; } @@ -3956,6 +3959,9 @@ static bool gbReadSaveState(gzFile gzFile) systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + if ( version >= 12 && utilReadInt( gzFile ) != 0x12345678 ) + assert( false ); // fails if something read too much/little from file + return true; } diff --git a/src/dmg/gbSound.cpp b/src/dmg/gbSound.cpp index da1bcc58..75079e11 100644 --- a/src/dmg/gbSound.cpp +++ b/src/dmg/gbSound.cpp @@ -43,8 +43,6 @@ extern int soundTicks; extern int SOUND_CLOCK_TICKS; extern u32 soundNextPosition; -extern int soundDebug; - extern bool soundEcho; extern bool soundLowPass; extern bool soundReverse; @@ -71,13 +69,6 @@ void gbSoundEvent(register u16 address, register int data) gbMemory[address] = data; -#ifndef FINAL_VERSION - if(soundDebug) { - // don't translate. debug only - log("Sound event: %08lx %02x\n", address, data); - } -#endif - if ( gb_apu && address >= NR10 && address <= 0xFF3F ) gb_apu->write_register( blip_time(), address, data ); } @@ -198,12 +189,6 @@ void gbSoundReset() soundPaused = 1; soundNextPosition = 0; - // don't translate -#ifndef FINAL_VERSION - if(soundDebug) { - log("*** Sound Init ***\n"); - } -#endif gbSoundEvent(0xff10, 0x80); gbSoundEvent(0xff11, 0xbf); gbSoundEvent(0xff12, 0xf3); @@ -229,12 +214,6 @@ void gbSoundReset() else gbSoundEvent(0xff26, 0xf1); - // don't translate -#ifndef FINAL_VERSION - if(soundDebug) { - log("*** Sound Init Complete ***\n"); - } -#endif int addr = 0xff30; while(addr < 0xff40) { @@ -271,12 +250,18 @@ void gbSoundSetQuality(int quality) } } -static char dummy_buf [735 * 2]; +static struct { + int version; + gb_apu_state_t apu; +} state; -#define SKIP( type, name ) { dummy_buf, sizeof (type) } +static char dummy_state [735 * 2]; -// funny expr at end ensures that type matches type of variable -#define LOAD( type, name ) { &name, sizeof (name) + (&name - (type*) &name) } +#define SKIP( type, name ) { dummy_state, sizeof (type) } + +#define LOAD( type, name ) { &name, sizeof (type) } + +// Old save state support static variable_desc gbsound_format [] = { @@ -362,11 +347,6 @@ static variable_desc gbsound_format3 [] = { NULL, 0 } }; -void gbSoundSaveGame(gzFile gzFile) -{ - // TODO: implement -} - enum { nr10 = 0, nr11, nr12, nr13, nr14, @@ -376,10 +356,18 @@ enum { nr50, nr51, nr52 }; -void gbSoundReadGame(int version,gzFile gzFile) +static void gbSoundReadGameOld(int version,gzFile gzFile) { - return; // TODO: apparently GB save states don't work in the main emulator - + if ( version == 11 ) + { + // Version 11 didn't save any state + // TODO: same for version 10? + state.apu.regs [nr50] = 0x77; // volume at max + state.apu.regs [nr51] = 0xFF; // channels enabled + state.apu.regs [nr52] = 0x80; // power on + return; + } + // Load state utilReadData( gzFile, gbsound_format ); @@ -395,9 +383,7 @@ void gbSoundReadGame(int version,gzFile gzFile) gbSoundSetQuality( quality ); // Convert to format Gb_Apu uses - reset_apu(); - gb_apu_state_t s; - gb_apu->save_state( &s ); // use fresh values for anything not restored + gb_apu_state_t& s = state.apu; // Only some registers are properly preserved static int const regs_to_copy [] = { @@ -407,6 +393,64 @@ void gbSoundReadGame(int version,gzFile gzFile) s.regs [regs_to_copy [i]] = gbMemory [0xFF10 + regs_to_copy [i]]; memcpy( &s.regs [0x20], &gbMemory [0xFF30], 0x10 ); // wave - - gb_apu->load_state( s ); +} + +// New state format + +static variable_desc gb_state [] = +{ + LOAD( int, state.version ), // room_for_expansion will be used by later versions + + // APU + LOAD( u8 [0x40], state.apu.regs ), // last values written to registers and wave RAM (both banks) + LOAD( int, state.apu.frame_time ), // clocks until next frame sequencer action + LOAD( int, state.apu.frame_phase ), // next step frame sequencer will run + + LOAD( int, state.apu.sweep_freq ), // sweep's internal frequency register + LOAD( int, state.apu.sweep_delay ), // clocks until next sweep action + LOAD( int, state.apu.sweep_enabled ), + LOAD( int, state.apu.sweep_neg ), // obscure internal flag + LOAD( int, state.apu.noise_divider ), + LOAD( int, state.apu.wave_buf ), // last read byte of wave RAM + + LOAD( int [4], state.apu.delay ), // clocks until next channel action + LOAD( int [4], state.apu.length_ctr ), + LOAD( int [4], state.apu.phase ), // square/wave phase, noise LFSR + LOAD( int [4], state.apu.enabled ), // internal enabled flag + + LOAD( int [3], state.apu.env_delay ), // clocks until next envelope action + LOAD( int [3], state.apu.env_volume ), + LOAD( int [3], state.apu.env_enabled ), + + SKIP( int [13], room_for_expansion ), + + // Emulator + SKIP( int [16], room_for_expansion ), + + { NULL, 0 } +}; + +void gbSoundSaveGame( gzFile out ) +{ + gb_apu->save_state( &state.apu ); + + // Be sure areas for expansion get written as zero + memset( dummy_state, 0, sizeof dummy_state ); + + state.version = 1; + utilWriteData( out, gb_state ); +} + +void gbSoundReadGame( int version, gzFile in ) +{ + // Prepare APU and default state + reset_apu(); + gb_apu->save_state( &state.apu ); + + if ( version > 11 ) + utilReadData( in, gb_state ); + else + gbSoundReadGameOld( version, in ); + + gb_apu->load_state( state.apu ); }