SPC700 Tracer
Moderator: ZSNES Mods
SPC700 Tracer
I'm trying to get my emulator to work with a (suposedly simple) demo (the one made by yoshi, the author of the docs) but I need to find out why both cpu's lock up in an infinite loop. So I would like to compare my data to one that's correct. I tried Super Sleuth but It doesn't trace SPC700 Data, I remember that zsnes dos did it once, but I don't remember how to activate it, if it does it now, and I just don't get how to use Geiger's Snes9x. So, any help would be great.
Regards
Regards
bsnes v0.013 (not any of the newer versions) traces SPC700 code. I don't know if it uses a trace mask or not though. I think it has one...
ZSNES doesn't log SPC700 commands even when SPC700 debug output is enabled, IIRC. Otherwise, 1 and 2 toggle output for CPU and APU (might have those reversed), and l logs the code to a file.
ZSNES doesn't log SPC700 commands even when SPC700 debug output is enabled, IIRC. Otherwise, 1 and 2 toggle output for CPU and APU (might have those reversed), and l logs the code to a file.
Hey thanks, I'll take a look at that. This thing is like looking for a needle in a haystack.
Edit: I have a question, do I have to step it through manually to trace the output to a file?
Edit: I have a question, do I have to step it through manually to trace the output to a file?
Last edited by Albert on Wed May 17, 2006 2:43 am, edited 1 time in total.
Heh, get used to it. It only gets harder and harder, with less and less games fixed for each bug you finally do track down. And then you end up getting to the point where your bug fix ends up breaking more than it fixed, even though it is a proper fix. More and more work for less and less reward, and yet the more you work on it, the more you want to continue working on it. Sound like anything else you know? ;)
None. They have separate timing crystals and run in parallel.
The SPC700 runs at ~24.576000mhz, the CPU runs at ~21.477272mhz (NTSC) and whatever for PAL, I forget. Each SPC700 opcode cycle is 24 master clocks on the SPC700 crystal. Each CPU opcode cycle is 6, 8 or 12 master clocks, depending on whether its read/write or i/o, whether fastrom is enabled and the ROM is fast enough, and which address is being read from/written to.
I guess the easiest way to sync the two is to do something like :
or
You can get away with making the APU timing crystal run at 1.024mhz and adding one clock per APU cycle, but you won't be able to simulate bus hold delays that way. The CPU, because it runs 6, 8 or 12 clocks per cycle, means you can only really reduce that clock by 1/2 (the only common denominator between all three numbers).
You can enslave the PPU to the CPU's timing crystal, and the DSP to the APU's timing crystal. But if you want to add timing for anything else (SA-1, SuperFX/2, etc), you'll have to come up with something more complex.
The SPC700 runs at ~24.576000mhz, the CPU runs at ~21.477272mhz (NTSC) and whatever for PAL, I forget. Each SPC700 opcode cycle is 24 master clocks on the SPC700 crystal. Each CPU opcode cycle is 6, 8 or 12 master clocks, depending on whether its read/write or i/o, whether fastrom is enabled and the ROM is fast enough, and which address is being read from/written to.
I guess the easiest way to sync the two is to do something like :
Code: Select all
void run() {
if(cpu.cycles <= apu.cycles) {
apu.cycles -= cpu.cycles;
//cpu.cycles = 0;
cpu.run();
//yes, this should be backwards, cpu cycles * -a-pu speed...
cpu.cycles = cpu.cycles_executed() * apu.clock_speed;
} else {
cpu.cycles -= apu.cycles;
//apu.cycles = 0;
apu.run();
//...and vice versa
apu.cycles = apu.cycles_executed() * cpu.clock_speed;
}
}
Code: Select all
void run() {
if(counter <= 0) {
cpu.run();
counter += cpu.cycles_executed() * apu.clock_speed;
} else {
apu.run();
counter -= apu.cycles_executed() * cpu.clock_speed;
}
}
You can enslave the PPU to the CPU's timing crystal, and the DSP to the APU's timing crystal. But if you want to add timing for anything else (SA-1, SuperFX/2, etc), you'll have to come up with something more complex.
I noticed my emulator was off in it's syncronization compared to bsnes, (opcode based interpreter). But tried your solution and it doesn't even finish the transfer of the program to the spc700 ram, so let me see if I get this. 'clock_speed' means the amount of cycles per the corresponding master clock (24 for the apu and 6/8/12 for the cpu), and cycles_executed() means the amount of cpu or apu cycles the opcode took. Is that correct?
The variable name means exactly what it says. clock_speed means the speed of the clock. 24576000 for apu.clock_speed, and 21477272 for cpu.clock_speed.
I really shouldn't have used cycles_executed. clocks_executed() would have been more correct. See, I used to call the clocks 'master cycles', hence the confusion.
So, say you execute the lda #$a9 opcode in SlowROM. 8 clocks + 8 clocks = 16 clock opcode.
counter += cpu.clocks_executed() * apu.clock_speed;
counter += 16 * 24576000;
Then you execute nop on the SPC700, 24 clocks + 24 clocks.
counter -= apu.clocks_executed() * cpu.clock_speed;
counter -= 48 * 21477272;
I really shouldn't have used cycles_executed. clocks_executed() would have been more correct. See, I used to call the clocks 'master cycles', hence the confusion.
So, say you execute the lda #$a9 opcode in SlowROM. 8 clocks + 8 clocks = 16 clock opcode.
counter += cpu.clocks_executed() * apu.clock_speed;
counter += 16 * 24576000;
Then you execute nop on the SPC700, 24 clocks + 24 clocks.
counter -= apu.clocks_executed() * cpu.clock_speed;
counter -= 48 * 21477272;
There, now it finishes the transfer, it just locks up in the transfered code. But there is an issue, it's still slightly off sync, so I think that's why it still gets locked in an endless loop. Is it correct to assume that if an instruction takes 7 cpu cycles then to the master clock it will be 7 * 6/8/12?
But that means that that the cpu does not have a constant frequecy... I would've never thought that... Well back to coding, thanks again
.
Edit: BTW how does an address from bus A translate to a ROM address?? either /cart or not, and what's the difference between LowROM and HiROM (I know the obvious difference, but is there another one besides a15 being high)?

Edit: BTW how does an address from bus A translate to a ROM address?? either /cart or not, and what's the difference between LowROM and HiROM (I know the obvious difference, but is there another one besides a15 being high)?