Misc fixes

This commit is contained in:
Snesrev 2023-06-13 23:38:53 +02:00
parent e6f0ae79a9
commit ae5a35b44c
11 changed files with 351 additions and 74 deletions

View File

@ -34,6 +34,9 @@ void UploadMainSampleData() {
}
void HandleSPCUploads_Main() {
if (g_use_my_apu_code)
RtlApuUpload(RomPtr(load24(R0_)));
return;
uint16 v0; // di
uint16 v1; // ax

View File

@ -38,7 +38,11 @@ static const uint32 kPatchedCarrys_SMB1[] = {
};
uint32 PatchBugs_SMB1(void) {
if (FixBugHook(0x088054) || FixBugHook(0x088007) || FixBugHook(0x088039) || FixBugHook(0x8827D)) {
if (FixBugHook(0x088054)) {
if (g_use_my_apu_code)
return 0x88AEA; // ret
RtlSetUploadingApu(true);
} else if (FixBugHook(0x088007) || FixBugHook(0x088039) || FixBugHook(0x8827D)) {
RtlSetUploadingApu(true);
} else if (FixBugHook(0x880C2)) {
RtlSetUploadingApu(false);
@ -126,6 +130,7 @@ void Smb1RunOneFrameOfGame(void) {
if (snes->cpu->pc == 0x8000) {
RESET_GAME:
snes->cpu->pc = 0x8001;
Smb1VectorReset();
}
Smb1RunOneFrameOfGame_Internal();

View File

@ -221,6 +221,8 @@ static const MemMapSized kSpcPlayer_Maps[] = {
{offsetof(SmasSpcPlayer, chan5_var25), 0x25, 1},
{offsetof(SmasSpcPlayer, enable_some_randomstuff), 0x26, 1},
{offsetof(SmasSpcPlayer, chan5_var27), 0x27, 1},
{offsetof(SmasSpcPlayer, timer_cycles), 0x28, 1},
{offsetof(SmasSpcPlayer, last_written_edl), 0x29, 1},
{offsetof(SmasSpcPlayer, sfx_sound_ptr_cur), 0x2c, 2},
{offsetof(SmasSpcPlayer, port0_note_length_left), 0x2e, 1},
{offsetof(SmasSpcPlayer, port0_note_length), 0x2f, 1},
@ -298,6 +300,7 @@ static void Randomstuff_Disable(SmasSpcPlayer *p);
static void Port1_FuncA(SmasSpcPlayer *p);
static void Chan7_WriteInstrumentData(SmasSpcPlayer *p, uint8 a);
static void Port1_HandleCmd(SmasSpcPlayer *p);
static void Chan7_Func1605(SmasSpcPlayer *p);
static const uint8 kEffectByteLength[27] = { 1, 1, 2, 3, 0, 1, 2, 1, 2, 1, 1, 3, 0, 1, 2, 3, 1, 3, 3, 0, 1, 3, 0, 3, 3, 3, 1 };
@ -353,6 +356,13 @@ static void SmasSpcPlayer_CopyVariablesFromRam(SmasSpcPlayer *p) {
p->channel[i].index = i;
}
static void SmasSpcPlayer_CopyVariables(SpcPlayer *p_in, bool copy_to_ram) {
SmasSpcPlayer *p = (SmasSpcPlayer *)p_in;
if (copy_to_ram)
SmasSpcPlayer_CopyVariablesToRam(p);
else
SmasSpcPlayer_CopyVariablesFromRam(p);
}
static inline void Chan_DoAnyFade(uint16 *p, uint16 add, uint8 target, uint8 cont) {
if (!cont)
@ -374,8 +384,6 @@ static void Spc_Reset(SmasSpcPlayer *p) {
Dsp_Write(p, MVOLR, 0x60);
Dsp_Write(p, DIR, 0x3c);
HIBYTE(p->tempo) = 16;
p->timer_cycles = 0;
}
static void Spc_Loop_Part1(SmasSpcPlayer *p) {
@ -394,6 +402,8 @@ static void Spc_Loop_Part1(SmasSpcPlayer *p) {
}
}
p->key_OFF = p->key_ON = 0;
uint8 bit = ((p->lfsr_value ^ (p->lfsr_value >> 8)) & 2 ? 0 : 0x80);
p->lfsr_value = swap16((swap16(p->lfsr_value) >> 1)) | bit;
}
static void Spc_Loop_Part2(SmasSpcPlayer *p, uint8 ticks) {
@ -502,7 +512,7 @@ static void WritePitch(SmasSpcPlayer *p, Channel *c, uint16 pitch) {
}
static void SomeRandomStuff(SmasSpcPlayer *p) {
uint8 *rp = p->ram + (--p->somerandomstuff_ctr & 3) * 0x3f;
uint8 *rp = p->ram + 0xfe00 + (--p->somerandomstuff_ctr & 3) * 0x3f;
for (int i = 0; i < 7; i++) {
rp += 1;
for (int j = 0; j < 4; j++) {
@ -712,7 +722,7 @@ less_0xf3:
p->some_volume_flag = 0;
p->port_to_snes_a[2] = a;
t = WORD(p->ram[0xc000 + (a - 1) * 2]);
if (HIBYTE(t) == 0) {
if ((t >> 8) == 0) {
p->port_to_snes_a[2] = 0;
return;
}
@ -898,7 +908,8 @@ static void ComputePitchAdd(Channel *c, uint8 pitch) {
}
static void SpcPlayer_Upload(SmasSpcPlayer *p, const uint8_t *data) {
static void SmasSpcPlayer_Upload(SpcPlayer *p_in, const uint8_t *data) {
SmasSpcPlayer *p = (SmasSpcPlayer *)p_in;
Dsp_Write(p, EVOLL, 0);
Dsp_Write(p, EVOLR, 0);
Dsp_Write(p, KOF, 0xff);
@ -922,6 +933,9 @@ static void SpcPlayer_Upload(SmasSpcPlayer *p, const uint8_t *data) {
p->extra_tempo = 0;
if (!p->var_3F8)
p->port_to_snes_a[2] = 0;
memset(p->base.input_ports, 0, sizeof(p->base.input_ports));
memset(p->last_value_from_snes, 0, sizeof(p->last_value_from_snes));
memset(p->new_value_from_snes, 0, sizeof(p->new_value_from_snes));
}
static void Channel_SetInstrument(SmasSpcPlayer *p, Channel *c, uint8 instrument) {
@ -1148,7 +1162,7 @@ static void Port0_HandleCmd(SmasSpcPlayer *p) {
if (p->new_value_from_snes[0] == 0x7f) {
p->extra_tempo = 10;
p->tempo = (HIBYTE(p->tempo) + 10) << 8;
p->tempo = (HIBYTE(p->tempo) + 11) << 8;
p->new_value_from_snes[3] = cmd = 0x1d;
goto label_a;
} else if (p->new_value_from_snes[0]) {
@ -1210,8 +1224,6 @@ label_c:
Dsp_Write(p, V4VOLR, cmd);
cmd = p->ram[++p->sfx_sound_ptr_cur];
}
} else {
cmd = p->ram[++p->sfx_sound_ptr_cur];
}
}
@ -1292,7 +1304,7 @@ static void Port3_HandleCmd(SmasSpcPlayer *p) {
return;
}
p->port_to_snes_a[3] = cmd;
p->port_to_snes_a[3] = p->new_value_from_snes[3];
p->port3_timeout = 2;
Dsp_Write(p, KOF, 0x40);
p->is_chan_on |= 0x40;
@ -1335,8 +1347,6 @@ lbl_begin:
Dsp_Write(p, V6VOLR, cmd);
cmd = p->ram[++p->port3_cur_ptr];
}
} else {
cmd = p->ram[++p->port3_cur_ptr];
}
}
@ -1469,10 +1479,10 @@ static void Chan7_WriteInstrumentData(SmasSpcPlayer *p, uint8 a) {
}
static void Port1_HandleCmd(SmasSpcPlayer *p) {
if (p->new_value_from_snes[3] == 0xff) {
if (p->new_value_from_snes[1] == 0xff) {
assert(0);
return;
} else if (p->new_value_from_snes[3] == 0xf0) {
} else if (p->new_value_from_snes[1] == 0xf0) {
assert(0);
return;
}
@ -1536,10 +1546,279 @@ static void Port1_HandleCmd(SmasSpcPlayer *p) {
WritePitch(p, &p->channel[7], p->channel[7].pitch);
}
} else if (p->port_to_snes_a[1] == 4) {
Chan7_Func1605(p);
}
}
static void Chan7_Func1605(SmasSpcPlayer *p) {
static const uint8 kChan7Notes[] = {0xB7, 0xB5, 0xB8, 0xB5, 0x70 };
if (p->chan7_timer != 0) {
if (!--p->chan7_timer) {
p->chan7_note_index = 5;
p->some_timer = 1;
Chan7_WriteInstrumentData(p, 1);
}
return;
}
if (--p->some_timer == 0) {
p->some_timer = 4;
if (--p->chan7_note_index != 0) {
PlayNote(p, &p->channel[7], kChan7Notes[p->chan7_note_index]);
Dsp_Write(p, V7VOLL, 20);
Dsp_Write(p, V7VOLR, 20);
Write_KeyOn(p, 0x80);
} else {
p->port_to_snes_a[1] = 0;
p->is_chan_on &= ~0x80;
p->channel[7].pitch_slide_length = 0;
p->channel[7].channel_transpositionb = p->channel[7].channel_transpositiona;
p->channel[7].fine_tunea = p->channel[7].fine_tuneb;
p->channel[7].pitch_envelope_num_ticksa = p->channel[7].pitch_envelope_num_ticksb;
Channel_SetInstrument(p, &p->channel[7], p->channel[7].instrument_id);
}
}
if (p->some_timer == 2)
Dsp_Write(p, KOF, 0x80);
}
static void SmasSpcPlayer_Initialize(SpcPlayer *p_in) {
SmasSpcPlayer *p = (SmasSpcPlayer *)p_in;
dsp_reset(p->base.dsp);
Spc_Reset(p);
Spc_Loop_Part1(p);
}
static void SmasSpcPlayer_GenerateSamples(SpcPlayer *p_in) {
SmasSpcPlayer *p = (SmasSpcPlayer *)p_in;
assert(p->timer_cycles <= 64);
assert(p->base.dsp->sampleOffset <= 534);
for (;;) {
if (p->timer_cycles >= 64) {
Spc_Loop_Part2(p, p->timer_cycles >> 6);
Spc_Loop_Part1(p);
p->timer_cycles &= 63;
}
// sample rate 32000
int n = 534 - p->base.dsp->sampleOffset;
if (n > (64 - p->timer_cycles))
n = (64 - p->timer_cycles);
p->timer_cycles += n;
for (int i = 0; i < n; i++)
dsp_cycle(p->base.dsp);
if (p->base.dsp->sampleOffset == 534)
break;
}
}
SpcPlayer *SmasSpcPlayer_Create(void) {
SmasSpcPlayer *p = (SmasSpcPlayer *)malloc(sizeof(SmasSpcPlayer));
memset(p, 0, sizeof(SmasSpcPlayer));
p->base.dsp = dsp_init(p->ram);
p->base.ram = p->ram;
p->base.initialize = &SmasSpcPlayer_Initialize;
p->base.gen_samples = &SmasSpcPlayer_GenerateSamples;
p->base.upload = &SmasSpcPlayer_Upload;
p->base.copy_vars = &SmasSpcPlayer_CopyVariables;
p->reg_write_history = 0;
return &p->base;
}
// =======================================
#define WITH_SPC_PLAYER_DEBUGGING 0
#if WITH_SPC_PLAYER_DEBUGGING
#include <SDL.h>
static DspRegWriteHistory my_write_hist;
static SmasSpcPlayer my_spc_snapshot;
static int loop_ctr;
bool CompareSpcImpls(SmasSpcPlayer *p, SmasSpcPlayer *p_org, Apu *apu) {
SmasSpcPlayer_CopyVariablesToRam(p);
memcpy(p->ram + 0x120, apu->ram + 0x120, 256 - 32); // stack
memcpy(p->ram + 0xf1, apu->ram + 0xf1, 15); // dsp regs
memcpy(p->ram + 0x10, apu->ram + 0x10, 8); // temp regs
memcpy(p->ram + 0x44, apu->ram + 0x44, 1); // chn
p->ram[0x46] = apu->ram[0x46]; // chn
int errs = 0;
static const uint16 ranges[][2] = {
{0x0, 0x500},
{0x1500, 0x2c00},
{0x3c00, 0xffff},
};
for (int j = 0; j < 2; j++) {
for (int i = ranges[j][0], i_end = ranges[j][1]; i != i_end; i++) { // skip compare echo etc
if (p->ram[i] != apu->ram[i]) {
if (errs < 16) {
if (errs == 0)
printf("@%d\n", loop_ctr);
printf("%.4X: %.2X != %.2X (mine, theirs) orig %.2X\n", i, p->ram[i], apu->ram[i], p_org->ram[i]);
errs++;
}
}
}
}
int n = my_write_hist.count < apu->hist.count ? apu->hist.count : my_write_hist.count;
for (size_t i = 0; i != n; i++) {
if (i >= my_write_hist.count || i >= apu->hist.count || my_write_hist.addr[i] != apu->hist.addr[i] || my_write_hist.val[i] != apu->hist.val[i]) {
if (errs == 0)
printf("@%d\n", loop_ctr);
printf("%d: ", (int)i);
if (i >= my_write_hist.count) printf("[??: ??]"); else printf("[%.2x: %.2x]", my_write_hist.addr[i], my_write_hist.val[i]);
printf(" != ");
if (i >= apu->hist.count) printf("[??: ??]"); else printf("[%.2x: %.2x]", apu->hist.addr[i], apu->hist.val[i]);
printf("\n");
errs++;
}
}
if (errs) {
printf("Total %d errors\n", errs);
return false;
}
apu->hist.count = 0;
my_write_hist.count = 0;
loop_ctr++;
return true;
}
extern bool g_debug_apu_cycles;
void RunAudioPlayer(void) {
if (SDL_Init(SDL_INIT_AUDIO) != 0) {
printf("Failed to init SDL: %s\n", SDL_GetError());
return;
}
SDL_AudioSpec want, have;
SDL_AudioDeviceID device;
SDL_memset(&want, 0, sizeof(want));
want.freq = 44100;
want.format = AUDIO_S16;
want.channels = 2;
want.samples = 2048;
want.callback = NULL; // use queue
device = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
if (device == 0) {
printf("Failed to open audio device: %s\n", SDL_GetError());
return;
}
int16_t *audioBuffer = (int16_t *)malloc(735 * 4); // *2 for stereo, *2 for sizeof(int16)
SDL_PauseAudioDevice(device, 0);
SmasSpcPlayer *p = (SmasSpcPlayer *)SmasSpcPlayer_Create();
FILE *f = fopen("d:/code/smw/smb1_dis/audio.spc", "rb");
fread(p->ram, 1, 65536, f);
fclose(f);
p->reg_write_history = &my_write_hist;
bool run_both = 1;
if (!run_both) {
SmasSpcPlayer_Initialize(&p->base);
p->base.input_ports[0] = 4;
for (;;) {
SmasSpcPlayer_GenerateSamples(&p->base);
int16_t audioBuffer[736 * 2];
dsp_getSamples(p->base.dsp, audioBuffer, 736);
SDL_QueueAudio(device, audioBuffer, 736 * 2 * have.channels);
while (SDL_GetQueuedAudioSize(device) >= 736 * 4 * 3/* 44100 * 4 * 300*/)
SDL_Delay(1);
}
} else {
Apu *apu = apu_init();
apu_reset(apu);
apu->spc->pc = 0x500;
memcpy(apu->ram, p->ram, 65536);
CompareSpcImpls(p, &my_spc_snapshot, apu);
// g_debug_apu_cycles = true;
uint64_t cycle_counter = 0;
int tgt = 0x57b;
uint8 ticks_next = 0;
bool apu_debug = 0;
bool is_initialize = true;
for (;;) {
if (apu_debug && apu->cpuCyclesLeft == 0) {
char line[80];
getProcessorStateSpc(apu, line);
puts(line);
}
apu_cycle(apu);
if (((apu->cycles - 1) & 0x1f) == 0)
dsp_cycle(p->base.dsp);
// if (apu->spc->pc == 0x14c1) {
// apu_debug = 1;
// }
if (apu->spc->pc == tgt) {
tgt ^= 0x57B ^ 0x57C;
if (tgt == 0x57B) {
uint8 ticks = ticks_next;
ticks_next = apu->spc->y;
my_spc_snapshot = *p;
for (;;) {
my_write_hist.count = 0;
if (is_initialize) {
SmasSpcPlayer_Initialize(&p->base);
} else {
Spc_Loop_Part2(p, ticks);
Spc_Loop_Part1(p);
}
if (CompareSpcImpls(p, &my_spc_snapshot, apu))
break;
*p = my_spc_snapshot;
}
is_initialize = false;
if (cycle_counter == 0)
apu->inPorts[2] = p->base.input_ports[2] = 15;
if (cycle_counter == 10000)
apu->inPorts[0] = p->base.input_ports[0] = 0x7f;
// if (cycle_counter == 2000)
// apu->inPorts[3] = p->base.input_ports[3] = cycle_counter / 500;
if (cycle_counter % 1000 == 0)
apu->inPorts[3] = p->base.input_ports[3] = cycle_counter / 1000 + 1;
// if (cycle_counter == 2000)
// apu->inPorts[1] = p->base.input_ports[1] = 3;
// if (cycle_counter == 3000)
// apu->inPorts[1] = p->base.input_ports[1] = 1;
cycle_counter++;
}
}
if (p->base.dsp->sampleOffset == 534) {
int16_t audioBuffer[736 * 2];
dsp_getSamples(p->base.dsp, audioBuffer, 736);
SDL_QueueAudio(device, audioBuffer, 736 * 2 * have.channels);
while (SDL_GetQueuedAudioSize(device) >= 736 * 4 * 3/* 44100 * 4 * 300*/) {
SDL_Delay(1);
}
}
}
}
}
#endif // WITH_SPC_PLAYER_DEBUGGING

View File

@ -34,6 +34,8 @@ void Smbll_UploadMainSampleData() {
}
void Smbll_HandleSPCUploads_Main() {
if (g_use_my_apu_code)
RtlApuUpload(RomPtr(load24(R0_)));
return;
uint16 v0; // di
uint16 v1; // ax

View File

@ -35,7 +35,11 @@ static const uint32 kPatchedCarrys_SMBLL[] = {
};
static uint32 PatchBugs_SMBLL(void) {
if (FixBugHook(0x088054) || FixBugHook(0x088007) || FixBugHook(0x088039) || FixBugHook(0x8817A)) {
if (FixBugHook(0x088054)) {
if (g_use_my_apu_code)
return 0x88168; // ret
RtlSetUploadingApu(true);
} else if (FixBugHook(0x088007) || FixBugHook(0x088039) || FixBugHook(0x8817A)) {
RtlSetUploadingApu(true);
} else if (FixBugHook(0x880C2)) {
RtlSetUploadingApu(false);
@ -125,6 +129,7 @@ void SmbllRunOneFrameOfGame(void) {
if (snes->cpu->pc == 0x8000) {
RESET_GAME:
snes->cpu->pc = 0x8001;
Smbll_VectorReset();
}
SmbllRunOneFrameOfGame_Internal();

View File

@ -8,7 +8,7 @@
#include <time.h>
enum RunMode { RM_BOTH, RM_MINE, RM_THEIRS };
uint8 g_runmode = RM_THEIRS;
uint8 g_runmode = RM_BOTH;
extern int g_got_mismatch_count;
@ -250,6 +250,7 @@ Snes *SnesInit(const char *filename) {
}
g_sram = g_snes->cart->ram;
g_sram_size = g_snes->cart->ramSize;
g_rom = g_snes->cart->rom;
RtlSetupEmuCallbacks(NULL, &RtlRunFrameCompare, NULL);
@ -262,8 +263,6 @@ Snes *SnesInit(const char *filename) {
g_rtl_game_info = &kSmwGameInfo;
}
game_id = g_rtl_game_info->game_id;
g_rtl_game_info->initialize();
@ -317,7 +316,6 @@ again_theirs:
if (g_fail) {
g_fail = false;
printf("Verify failure!\n");
g_snes->ppu = g_snes->snes_ppu;
@ -355,7 +353,7 @@ static void RtlRunFrameCompare(uint16 input, int run_what) {
g_rtl_game_info->run_frame();
g_snes->runningWhichVersion = 0;
} else {
g_use_my_apu_code = true;
g_use_my_apu_code = true;
RunOneFrameOfGame_Both();
}
}

View File

@ -13,6 +13,7 @@ void SmwSavePlaythroughSnapshot();
uint8 g_ram[0x20000];
uint8 *g_sram;
int g_sram_size;
const uint8 *g_rom;
bool g_is_uploading_apu;
bool g_did_finish_level_hook;
@ -159,7 +160,7 @@ void RtlReset(int mode) {
snes_frame_counter = 0;
snes_reset(g_snes, true);
if (!(mode & 1))
memset(g_sram, 0, RTL_SRAM_SIZE);
memset(g_sram, 0, g_sram_size);
RtlApuLock();
RtlRestoreMusicAfterLoad_Locked(true);
@ -191,7 +192,6 @@ void StateRecorder_Load(StateRecorder *sr, FILE *f, bool replay_mode) {
hdr[5] = (hdr[5] & 1) ? hdr[6] : 0;
} else if (hdr[0] == 2) {
ReadFromFile(f, hdr + 8, 8 * sizeof(uint32));
} else {
assert(0);
}
@ -220,8 +220,8 @@ void StateRecorder_Load(StateRecorder *sr, FILE *f, bool replay_mode) {
assert(state.p == state.pend);
} else {
RtlReset(2);
if (sr->base_snapshot.size == RTL_SRAM_SIZE)
memcpy(g_sram, sr->base_snapshot.data, RTL_SRAM_SIZE);
if (sr->base_snapshot.size == g_sram_size)
memcpy(g_sram, sr->base_snapshot.data, g_sram_size);
is_reset = true;
}
} else {
@ -237,7 +237,7 @@ void StateRecorder_Load(StateRecorder *sr, FILE *f, bool replay_mode) {
if (hdr[6] == 269349) {
// In the snapshot that's 269349 bytes big, the cart RAM is at 0x213eb
printf("Warning. Old snapshot not supported! Reading only SRAM!\n");
memcpy(g_snes->cart->ram, arr.data + 0x213eb, RTL_SRAM_SIZE);
memcpy(g_snes->cart->ram, arr.data + 0x213eb, g_sram_size);
} else {
LoadFuncState state = { {&loadFunc }, arr.data, arr.data, arr.data + arr.size };
LoadSnesState(&state.base);
@ -259,7 +259,7 @@ void StateRecorder_Save(StateRecorder *sr, FILE *f, bool saving_with_bug) {
SaveFuncState savest = { {&saveFunc} };
SaveSnesState(&savest.base);
assert(sr->base_snapshot.size == 0 ||
sr->base_snapshot.size == savest.array.size || sr->base_snapshot.size == RTL_SRAM_SIZE);
sr->base_snapshot.size == savest.array.size || sr->base_snapshot.size == g_sram_size);
hdr[0] = 2;
hdr[1] = sr->total_frames;
@ -592,6 +592,7 @@ static uint8 g_apu_write_ent_pos, g_apu_queue_size, g_apu_time_since_empty;
void RtlSetUploadingApu(bool uploading) {
RtlApuLock();
if (g_is_uploading_apu != uploading && !g_use_my_apu_code) {
if (!uploading) {
g_snes->apuCatchupCycles = 10000;
snes_catchupApu(g_snes);
@ -663,51 +664,48 @@ static void RtlPopApuState_Locked(void) {
}
}
static void RtlResetApuQueue(void) {
static void RtlResetApuQueue_Locked(void) {
g_apu_write_ent_pos = g_apu_time_since_empty = g_apu_queue_size = 0;
memset(g_apu_write.ports, 0, sizeof(g_apu_write.ports));
uint8 *input_ports = g_use_my_apu_code ? g_spc_player->input_ports : g_snes->apu->inPorts;
memcpy(g_apu_write.ports, input_ports, sizeof(g_apu_write.ports));
}
void RtlApuUpload(const uint8 *p) {
RtlApuLock();
RtlResetApuQueue();
g_spc_player->upload(g_spc_player, p);
RtlResetApuQueue_Locked();
RtlApuUnlock();
}
void RtlApuReset() {
RtlApuLock();
g_spc_player->initialize(g_spc_player);
apu_reset(g_snes->apu);
RtlResetApuQueue_Locked();
RtlApuUnlock();
}
void RtlRestoreMusicAfterLoad_Locked(bool is_reset) {
if (g_use_my_apu_code) {
memcpy(g_spc_player->ram, g_snes->apu->ram, 65536);
memcpy(g_spc_player->input_ports, g_snes->apu->inPorts, 4);
memcpy(g_spc_player->dsp->ram, g_snes->apu->dsp->ram, sizeof(Dsp) - offsetof(Dsp, ram));
g_spc_player->copy_vars(g_spc_player, false);
}
if (is_reset) {
g_spc_player->initialize(g_spc_player);
}
RtlResetApuQueue();
RtlResetApuQueue_Locked();
}
void RtlSaveMusicStateToRam_Locked(void) {
if (g_use_my_apu_code) {
SpcPlayer *spc_player = g_spc_player;
uint8 tmp[4];
memcpy(tmp, spc_player->input_ports, 4);
memcpy(spc_player->input_ports, g_apu_write.ports, 4);
g_spc_player->copy_vars(g_spc_player, true);
memcpy(g_snes->apu->dsp->ram, g_spc_player->dsp->ram, sizeof(Dsp) - offsetof(Dsp, ram));
memcpy(g_snes->apu->ram, g_spc_player->ram, 65536);
memcpy(spc_player->input_ports, tmp, 4);
memcpy(g_snes->apu->inPorts, g_spc_player->input_ports, 4);
}
}
@ -743,12 +741,12 @@ void RtlReadSram(void) {
snprintf(filename, sizeof(filename), "saves/%s.srm", g_rtl_game_info->title);
FILE *f = fopen(filename, "rb");
if (f) {
if (fread(g_sram, 1, RTL_SRAM_SIZE, f) != RTL_SRAM_SIZE)
if (fread(g_sram, 1, g_sram_size, f) != g_sram_size)
fprintf(stderr, "Error reading %s\n", filename);
fclose(f);
RtlSynchronizeWholeState();
ByteArray_Resize(&state_recorder.base_snapshot, RTL_SRAM_SIZE);
memcpy(state_recorder.base_snapshot.data, g_sram, RTL_SRAM_SIZE);
ByteArray_Resize(&state_recorder.base_snapshot, g_sram_size);
memcpy(state_recorder.base_snapshot.data, g_sram, g_sram_size);
}
}
@ -759,7 +757,7 @@ void RtlWriteSram(void) {
rename(filename, filename_bak);
FILE *f = fopen(filename, "wb");
if (f) {
fwrite(g_sram, 1, RTL_SRAM_SIZE, f);
fwrite(g_sram, 1, g_sram_size, f);
fclose(f);
} else {
fprintf(stderr, "Unable to write %s\n", filename);

View File

@ -11,8 +11,8 @@ enum {
};
extern uint8 g_ram[0x20000];
#define RTL_SRAM_SIZE 0x800
extern uint8 *g_sram;
extern int g_sram_size;
extern const uint8 *g_rom;
#define GET_BYTE(p) (*(uint8*)(p))

View File

@ -403,7 +403,12 @@ int main(int argc, char** argv) {
g_audio_mutex = SDL_CreateMutex();
if (!g_audio_mutex) Die("No mutex");
g_spc_player = SmwSpcPlayer_Create();
if (g_rtl_game_info->game_id == kGameID_SMB1 ||
g_rtl_game_info->game_id == kGameID_SMBLL)
g_spc_player = SmasSpcPlayer_Create();
else if (g_rtl_game_info->game_id == kGameID_SMW)
g_spc_player = SmwSpcPlayer_Create();
g_spc_player->initialize(g_spc_player);
bool enable_audio = true;

View File

@ -198,6 +198,7 @@ static const MemMapSized kSpcPlayer_Maps[] = {
{offsetof(SmwSpcPlayer, key_ON), 0x47, 1},
{offsetof(SmwSpcPlayer, cur_chan_bit), 0x48, 1},
{offsetof(SmwSpcPlayer, main_tempo_accum), 0x49, 1},
{offsetof(SmwSpcPlayer, timer_cycles), 0x4a, 1},
{offsetof(SmwSpcPlayer, tempo), 0x50, 2},
{offsetof(SmwSpcPlayer, tempo_fade_num_ticks), 0x52, 1},
{offsetof(SmwSpcPlayer, tempo_fade_final), 0x53, 1},
@ -316,10 +317,11 @@ static void Spc_Reset(SmwSpcPlayer *p) {
SmwSpcPlayer_CopyVariablesFromRam(p);
memset(p->base.input_ports, 0, sizeof(p->base.input_ports));
for (int i = 11; i >= 0; i--)
Dsp_Write(p, kDefDspRegs[i], kDefDspValues[i]);
HIBYTE(p->tempo) = 0x36;
p->timer_cycles = 0;
}
static void Spc_Loop_Part2(SmwSpcPlayer *p, uint8 ticks) {
@ -355,9 +357,10 @@ static void Spc_Loop_Part2(SmwSpcPlayer *p, uint8 ticks) {
static void ReadPortFromSnes(SmwSpcPlayer *p, int port) {
uint8 old = p->last_value_from_snes[port];
p->last_value_from_snes[port] = p->base.input_ports[port];
if (p->base.input_ports[port] != old)
if (p->base.input_ports[port] != old) {
p->new_value_from_snes[port] = p->base.input_ports[port];
else
} else
p->new_value_from_snes[port] = 0;
}
@ -1271,30 +1274,6 @@ static void CalcFinalVolume(SmwSpcPlayer *p, Channel *c, uint8 vol) {
c->final_volume = t * t >> 8;
}
static void SpcPlayer_GenerateSamples(SmwSpcPlayer *p) {
assert(p->timer_cycles <= 64);
assert(p->base.dsp->sampleOffset <= 534);
for (;;) {
if (p->timer_cycles >= 64) {
Spc_Loop_Part2(p, p->timer_cycles >> 6);
p->timer_cycles &= 63;
}
// sample rate 32000
int n = 534 - p->base.dsp->sampleOffset;
if (n > (64 - p->timer_cycles))
n = (64 - p->timer_cycles);
p->timer_cycles += n;
for (int i = 0; i < n; i++)
dsp_cycle(p->base.dsp);
if (p->base.dsp->sampleOffset == 534)
break;
}
}
static void SmwSpcPlayer_Initialize(SpcPlayer *p_in) {
SmwSpcPlayer *p = (SmwSpcPlayer *)p_in;
dsp_reset(p->base.dsp);
@ -1347,10 +1326,12 @@ static void SmwSpcPlayer_Upload(SpcPlayer *p_in, const uint8_t *data) {
p->smw_pause_music = 0;
p->smw_player_on_yoshi = 0;
p->echo_channels = 0;
Dsp_Write(p, FLG, 0x20);
memset(p->base.input_ports, 0, sizeof(p->base.input_ports));
memset(p->last_value_from_snes, 0, sizeof(p->last_value_from_snes));
memset(p->new_value_from_snes, 0, sizeof(p->new_value_from_snes));
Dsp_Write(p, FLG, 0x20);
}
SpcPlayer *SmwSpcPlayer_Create(void) {
SmwSpcPlayer *p = (SmwSpcPlayer *)malloc(sizeof(SmwSpcPlayer));
memset(p, 0, sizeof(SmwSpcPlayer));

View File

@ -22,5 +22,6 @@ typedef struct SpcPlayer {
} SpcPlayer;
SpcPlayer *SmwSpcPlayer_Create();
SpcPlayer *SmwSpcPlayer_Create(void);
SpcPlayer *SmasSpcPlayer_Create(void);