mirror of https://github.com/snesrev/smw.git
Misc fixes
This commit is contained in:
parent
e6f0ae79a9
commit
ae5a35b44c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -22,5 +22,6 @@ typedef struct SpcPlayer {
|
|||
} SpcPlayer;
|
||||
|
||||
|
||||
SpcPlayer *SmwSpcPlayer_Create();
|
||||
SpcPlayer *SmwSpcPlayer_Create(void);
|
||||
SpcPlayer *SmasSpcPlayer_Create(void);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue