FIXED GB audio state loading [blargg]

This commit is contained in:
spacy51 2008-08-25 22:02:15 +00:00
parent a5179953ab
commit 79cc82a59f
2 changed files with 89 additions and 39 deletions

View File

@ -20,6 +20,7 @@
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <assert.h>
#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;
}

View File

@ -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,9 +356,17 @@ 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 );
}