FIXED GB audio state loading [blargg]
This commit is contained in:
parent
a5179953ab
commit
79cc82a59f
|
@ -20,6 +20,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "../System.h"
|
#include "../System.h"
|
||||||
#include "../NLS.h"
|
#include "../NLS.h"
|
||||||
|
@ -591,7 +592,8 @@ u8 ZeroTable[256] = {
|
||||||
#define GBSAVE_GAME_VERSION_9 9
|
#define GBSAVE_GAME_VERSION_9 9
|
||||||
#define GBSAVE_GAME_VERSION_10 10
|
#define GBSAVE_GAME_VERSION_10 10
|
||||||
#define GBSAVE_GAME_VERSION_11 11
|
#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)
|
int inline gbGetValue(int min,int max,int v)
|
||||||
{
|
{
|
||||||
|
@ -3565,6 +3567,7 @@ static bool gbWriteSaveState(gzFile gzFile)
|
||||||
utilWriteInt(gzFile, gbWindowLine);
|
utilWriteInt(gzFile, gbWindowLine);
|
||||||
utilWriteInt(gzFile, inUseRegister_WY);
|
utilWriteInt(gzFile, inUseRegister_WY);
|
||||||
utilWriteInt(gzFile, gbScreenOn);
|
utilWriteInt(gzFile, gbScreenOn);
|
||||||
|
utilWriteInt(gzFile, 0x12345678); // end marker
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3956,6 +3959,9 @@ static bool gbReadSaveState(gzFile gzFile)
|
||||||
|
|
||||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||||
|
|
||||||
|
if ( version >= 12 && utilReadInt( gzFile ) != 0x12345678 )
|
||||||
|
assert( false ); // fails if something read too much/little from file
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,6 @@ extern int soundTicks;
|
||||||
extern int SOUND_CLOCK_TICKS;
|
extern int SOUND_CLOCK_TICKS;
|
||||||
extern u32 soundNextPosition;
|
extern u32 soundNextPosition;
|
||||||
|
|
||||||
extern int soundDebug;
|
|
||||||
|
|
||||||
extern bool soundEcho;
|
extern bool soundEcho;
|
||||||
extern bool soundLowPass;
|
extern bool soundLowPass;
|
||||||
extern bool soundReverse;
|
extern bool soundReverse;
|
||||||
|
@ -71,13 +69,6 @@ void gbSoundEvent(register u16 address, register int data)
|
||||||
|
|
||||||
gbMemory[address] = 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 )
|
if ( gb_apu && address >= NR10 && address <= 0xFF3F )
|
||||||
gb_apu->write_register( blip_time(), address, data );
|
gb_apu->write_register( blip_time(), address, data );
|
||||||
}
|
}
|
||||||
|
@ -198,12 +189,6 @@ void gbSoundReset()
|
||||||
soundPaused = 1;
|
soundPaused = 1;
|
||||||
soundNextPosition = 0;
|
soundNextPosition = 0;
|
||||||
|
|
||||||
// don't translate
|
|
||||||
#ifndef FINAL_VERSION
|
|
||||||
if(soundDebug) {
|
|
||||||
log("*** Sound Init ***\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
gbSoundEvent(0xff10, 0x80);
|
gbSoundEvent(0xff10, 0x80);
|
||||||
gbSoundEvent(0xff11, 0xbf);
|
gbSoundEvent(0xff11, 0xbf);
|
||||||
gbSoundEvent(0xff12, 0xf3);
|
gbSoundEvent(0xff12, 0xf3);
|
||||||
|
@ -229,12 +214,6 @@ void gbSoundReset()
|
||||||
else
|
else
|
||||||
gbSoundEvent(0xff26, 0xf1);
|
gbSoundEvent(0xff26, 0xf1);
|
||||||
|
|
||||||
// don't translate
|
|
||||||
#ifndef FINAL_VERSION
|
|
||||||
if(soundDebug) {
|
|
||||||
log("*** Sound Init Complete ***\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
int addr = 0xff30;
|
int addr = 0xff30;
|
||||||
|
|
||||||
while(addr < 0xff40) {
|
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 SKIP( type, name ) { dummy_state, sizeof (type) }
|
||||||
#define LOAD( type, name ) { &name, sizeof (name) + (&name - (type*) &name) }
|
|
||||||
|
#define LOAD( type, name ) { &name, sizeof (type) }
|
||||||
|
|
||||||
|
// Old save state support
|
||||||
|
|
||||||
static variable_desc gbsound_format [] =
|
static variable_desc gbsound_format [] =
|
||||||
{
|
{
|
||||||
|
@ -362,11 +347,6 @@ static variable_desc gbsound_format3 [] =
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
void gbSoundSaveGame(gzFile gzFile)
|
|
||||||
{
|
|
||||||
// TODO: implement
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
nr10 = 0,
|
nr10 = 0,
|
||||||
nr11, nr12, nr13, nr14,
|
nr11, nr12, nr13, nr14,
|
||||||
|
@ -376,10 +356,18 @@ enum {
|
||||||
nr50, nr51, nr52
|
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
|
// Load state
|
||||||
utilReadData( gzFile, gbsound_format );
|
utilReadData( gzFile, gbsound_format );
|
||||||
|
|
||||||
|
@ -395,9 +383,7 @@ void gbSoundReadGame(int version,gzFile gzFile)
|
||||||
gbSoundSetQuality( quality );
|
gbSoundSetQuality( quality );
|
||||||
|
|
||||||
// Convert to format Gb_Apu uses
|
// Convert to format Gb_Apu uses
|
||||||
reset_apu();
|
gb_apu_state_t& s = state.apu;
|
||||||
gb_apu_state_t s;
|
|
||||||
gb_apu->save_state( &s ); // use fresh values for anything not restored
|
|
||||||
|
|
||||||
// Only some registers are properly preserved
|
// Only some registers are properly preserved
|
||||||
static int const regs_to_copy [] = {
|
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]];
|
s.regs [regs_to_copy [i]] = gbMemory [0xFF10 + regs_to_copy [i]];
|
||||||
|
|
||||||
memcpy( &s.regs [0x20], &gbMemory [0xFF30], 0x10 ); // wave
|
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 );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue