SPC700 timers

Strictly for discussing ZSNES development and for submitting code. You can also join us on IRC at irc.libera.chat in #zsnes.
Please, no requests here.

Moderator: ZSNES Mods

byuu

SPC700 timers

Post by byuu »

I followed anomie's document and sfsound.txt to try and emulate the SPC700 timers, would anyone mind taking a quick look and see if I got it right, or if there are any glaring mistakes? For the life of me I can't seem to figure out what ZSNES is doing with the timers, every time I poll them I get totally random values. I know ZSNES' SPC700 core runs way faster than its supposed to, but since the timers are based on SPC700 clock cycles, I can't understand what's going on.

The source code and some sample runs is here:
http://byuu.org/files/spc_timers.txt
(I removed everything not related to the timers from the routines)

The main questions I have are:
1) anomie's document doesn't mention what happens when you read TnOUT registers, but sfsound.txt says it resets "CN0". Does this just reset the stage 3 counter only?
2) Do 0->1 transitions in $f1/writes to $fd-$ff reset both stage 2 and 3 timers?
3) In spc700.txt, I see this:
"Stage 1: 128:1 (T0, T1) or 16:1 (T2) scaler.
Stage 2: 1-256 'divisor', based on a 0-255 wraparound counter and a post-increment comparator."
What's with the 0-255 wraparound counter? This plus sfsound.txt's cryptic description lead me to believe that stage 1 was incremented until it wrapped at 256, and THEN it sent a pulse to stage 2. But that results in an unbelievably slow counter (t2 = 250 ticks/second max). But if that isn't the case, then why even have a stage 1 counter? Why not just say the cycle counter that sends pulses to stage 2 runs nonstop instead?
4) I couldn't follow what happens when you write to TnTARGET while the timer is active, but it's probably not important anyway.

Also, somewhat offtopic. What's up with bits 4-5 in $f1? If they set $f4-$f7 to zero, but the CPU doesn't see it, then why bother setting them to zero? If the APU tries to read from them, it gets the CPU-side values, so ... what gives?
anomie
Lurker
Posts: 151
Joined: Tue Dec 07, 2004 1:40 am

Re: SPC700 timers

Post by anomie »

byuusan wrote:would anyone mind taking a quick look and see if I got it right, or if there are any glaring mistakes?
Only one glaring mistake, and that's actually something TRAC and I discovered recently. The TnOUT registers are not reset on write. However, most of the memory-targeting MOV instructions actually seem to act like read-modify-write instructions ($AF and $FA are the only exceptions, and $DA (MOVW) reads the low but not the high byte of the word). So it's the rather pointless read cycle in "MOV $ff, #$00" that's actually resetting T2OUT.
1) anomie's document doesn't mention what happens when you read TnOUT registers, but sfsound.txt says it resets "CN0". Does this just reset the stage 3 counter only?
Yes it does: "Stage 3 mey be read from TnOUT, and the value is zeroed on read."
2) Do 0->1 transitions in $f1/writes to $fd-$ff reset both stage 2 and 3 timers?
0->1 in $f1 resets both. Reading $fd-$ff resets only Stage 3. Writing $fd-$ff does nothing (see above).
3) In spc700.txt, I see this:
"Stage 1: 128:1 (T0, T1) or 16:1 (T2) scaler.
Stage 2: 1-256 'divisor', based on a 0-255 wraparound counter and a post-increment comparator."
What's with the 0-255 wraparound counter? This plus sfsound.txt's cryptic description lead me to believe that stage 1 was incremented until it wrapped at 256, and THEN it sent a pulse to stage 2. But that results in an unbelievably slow counter (t2 = 250 ticks/second max). But if that isn't the case, then why even have a stage 1 counter? Why not just say the cycle counter that sends pulses to stage 2 runs nonstop instead?
4) I couldn't follow what happens when you write to TnTARGET while the timer is active, but it's probably not important anyway.
The Stage 2 description is so confusing because of #4 there. Basically, Stage 1 counts up to 128 or 16, then ticks and resets. Stage 2 increments (in the range 0-255, i.e. it's 8 bits) then compares itself for equality to target to determine whether to tick-and-reset or not. So if you go and set target >= the current value of Stage 2, it will have to count all the way up to 255 and wrap around before it can compare equal to target. So the first tick to Stage 3 might be delayed much longer than otherwise expected.

Anyway, it looks like you have it right, why not try it? ;)
Also, somewhat offtopic. What's up with bits 4-5 in $f1? If they set $f4-$f7 to zero, but the CPU doesn't see it, then why bother setting them to zero? If the APU tries to read from them, it gets the CPU-side values, so ... what gives?
It sets the value the SPC700 will read; it overrides the CPU-side values, until the CPU sets new values. Useful for getting into a known state before you start waiting for a command byte.
byuu

Re: SPC700 timers

Post by byuu »

The TnOUT registers are not reset on write. However, most of the memory-targeting MOV instructions actually seem to act like read-modify-write instructions ($AF and $FA are the only exceptions, and $DA (MOVW) reads the low but not the high byte of the word). So it's the rather pointless read cycle in "MOV $ff, #$00" that's actually resetting T2OUT.
Fascinating. Are you going to go through and test all of the opcodes individually and document this behavior? I could give you a hand with a few of them if you like.
Yes it does: "Stage 3 mey be read from TnOUT, and the value is zeroed on read."
Hmm, my fault again. I don't know how I miss these things sometimes...
The Stage 2 description is so confusing because of #4 there. Basically, Stage 1 counts up to 128 or 16, then ticks and resets.
Oooooh. Your stage 1 is the cycle counter. Now it makes perfect sense. I thought stage 1 was a counter that only incremented once every 16/128 cycles. Hence why I have a useless extra counter in there.
So if you go and set target >= the current value of Stage 2, it will have to count all the way up to 255 and wrap around before it can compare equal to target. So the first tick to Stage 3 might be delayed much longer than otherwise expected.
Hm, the best way I can think of emulating this will be to set writes to $fa-$fc to temp_TnTARGET, and then only change the TnTARGET to whatever the temp_ variable is when it actually wraps back to zero via the current TnTARGET value, unless of course you write to TnTARGET when the timer is disabled in $f1 bits 2,1,0.
Anyway, it looks like you have it right, why not try it? ;)
Well, I've got a million and a half other bugs/problems in my SPC700 core, so I can only run tiny snippet programs I write myself at the moment. And I didn't want to dredge out the old copier, so I was relying on the results from the almighty ZSNES again :D
But if you say my code's good, I trust that a lot more than the results from... well, you get the idea ;)

That answers all of my questions and then some. Fantastic post, thank you much.
grinvader
ZSNES Shake Shake Prinny
Posts: 5632
Joined: Wed Jul 28, 2004 4:15 pm
Location: PAL50, dood !

Re: SPC700 timers

Post by grinvader »

byuusan wrote:For the life of me I can't seem to figure out what ZSNES is doing with the timers, every time I poll them I get totally random values.
(...)
I was relying on the results from the almighty ZSNES again
Man.

Code: Select all

<grinvader> hmm, how could we enhance our spc700 sync/core ?
<grinvader> it would be cool to suddenly fix 90% of games having trouble
<grinvader> like BOF2 , actraiser 2 and cuonpa
<pagefault> we need to enable cycle counting first
<grinvader> we currently DO NOT count the spc700 cycles ?
<grinvader> * facepalms
(...)
<pagefault> the problem with games is not really SPC cycle counting
<pagefault> it's 65816->SPC ratio
<grinvader> isn't it something like 1 for 4 ?
<grinvader> (or anything simple like that ?)
<pagefault> well yeah
<pagefault> but the 65816 has to be accurate
Zsnes is NOT a reference for spc700 behaviour.
Or anything critically important timing-wise.
皆黙って俺について来い!!

Code: Select all

<jmr> bsnes has the most accurate wiki page but it takes forever to load (or something)
Pantheon: Gideon Zhi | CaitSith2 | Nach | kode54
byuu

Post by byuu »

Code: Select all

<grinvader> we currently DO NOT count the spc700 cycles ?
<grinvader> * facepalms
o__O
Holy......... wow. Well, that certainly explains it then. I figured that ZSNES would at least have the little SPC700 cycle count table in there. With just that alone, the timers would work. The 65816<>SPC700 ratio would be irrelevent to the timer results.

As far as syncing the CPU with the APU, I recently came up with perhaps the simplest implementation possible. Just use this code:

Code: Select all

//frequencies reduced by LCD of 8 so that debt.sync doesn't overflow/underflow as easily.
#define CPUFREQ (21477272 / 8)
#define APUFREQ (24576000 / 8)

struct { int debt; }sync;
void add_apu_cycles(int cycles) { sync.debt -= CPUFREQ * cycles; }
void add_cpu_cycles(int cycles) { sync.debt += APUFREQ * cycles; }

void run() {
  if(sync.debt >= 0) { run_apu(); }
  else { run_cpu(); }
}
...of course, you'd need an SPC700 cycle table, a DMA implementation that synced with the APU every byte transfer rather than blasting the entire transfer out in one shot, etc. Otherwise, you'd probably want to divide the above frequencies by 256 or so to allow enough cycles to pass either way to avoid errors.

While we're on the topic of ZSNES, I may have spotted a potential bug. A while back, ZSNES implemented not clearing WRAM on reset. Shortly after, the same was done for the SPCRAM. However, I noticed ZSNES starts SPC700 execution at 0xffc9 instead of 0xffc0. That skips the stack initialization + RAM initialization of 0x0001-0x00ef (0x0001 is not a typo) to 0x00. Combined with you now clearing the SPCRAM... that might cause some issues if you don't still manually clear that area of RAM upon reset. And I can't imagine why you would if you cleared the entire thing upon reset before. I don't have the latest build to check into that, but it might be worth looking into.
grinvader
ZSNES Shake Shake Prinny
Posts: 5632
Joined: Wed Jul 28, 2004 4:15 pm
Location: PAL50, dood !

Post by grinvader »

byuusan wrote:However, I noticed ZSNES starts SPC700 execution at 0xffc9 instead of 0xffc0. That skips the stack initialization + RAM initialization of 0x0001-0x00ef (0x0001 is not a typo) to 0x00. Combined with you now clearing the SPCRAM... that might cause some issues if you don't still manually clear that area of RAM upon reset. And I can't imagine why you would if you cleared the entire thing upon reset before. I don't have the latest build to check into that, but it might be worth looking into.
Wow. This is really helpful. Thanks a lot for pointing it out - it may be the cause of some serious sound issues after reset in some games.
皆黙って俺について来い!!

Code: Select all

<jmr> bsnes has the most accurate wiki page but it takes forever to load (or something)
Pantheon: Gideon Zhi | CaitSith2 | Nach | kode54
byuu

Post by byuu »

No problem. ZSNES most likely starts the SPC700 at 0xffc9 as a speedhack. If you just set that back to 0xffc0, it should be fine. People debugging can get to 0xffc9 using the 's' key.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

byuusan wrote: While we're on the topic of ZSNES, I may have spotted a potential bug. A while back, ZSNES implemented not clearing WRAM on reset. Shortly after, the same was done for the SPCRAM. However, I noticed ZSNES starts SPC700 execution at 0xffc9 instead of 0xffc0. That skips the stack initialization + RAM initialization of 0x0001-0x00ef (0x0001 is not a typo) to 0x00. Combined with you now clearing the SPCRAM... that might cause some issues if you don't still manually clear that area of RAM upon reset. And I can't imagine why you would if you cleared the entire thing upon reset before. I don't have the latest build to check into that, but it might be worth looking into.
We do have sound issues in Super E.D.F. upon reset. Can you please explain more what you mean by how to properly setup SPCRAM and it's stack on reset (not init)? I couldn't follow so well which parts you meant to say we used to, what we do now, and what we should do.

You also mention that a large segment of SPC RAM should be set to 0x00 on reset. Since when is SPC RAM ever set to 0x00 for a segment longer than 32 bytes? On init it alternates 0xFF and 0x00.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
byuu

Post by byuu »

Sorry, I'll try to be more clear.

We know that upon SNES power-on, SPCRAM is initialized to random values that vary depending on who does the test.

We also know that upon SNES reset, SPCRAM is not touched at all. However, the IPLROM is enabled in register $f1, and the PC is set to 0xffc0. The flag register is (as a best guess) set to 0x02.

The IPLROM disassembly is as follows, keep in mind that the P flag is cleared upon reset as well:

Code: Select all

/*ffc0*/ 0xcd, 0xef,       //mov   x,#$ef
/*ffc2*/ 0xbd,             //mov   sp,x
/*ffc3*/ 0xe8, 0x00,       //mov   a,#$00
/*ffc5*/ 0xc6,             //mov   (x),a
/*ffc6*/ 0x1d,             //dec   x
/*ffc7*/ 0xd0, 0xfc,       //bne   $ffc5
/*ffc9*/ 0x8f, 0xaa, 0xf4, //mov   $f4,#$aa
For those who can't follow the SPC700 code, it's equivalent to:

Code: Select all

stack_pointer = 0xef;
regs.a = regs.x = 0x00;
for(int i=0x00ef;i>0x0000;i--)spcram[i] = 0x00;
The above code is never executed in ANY version of ZSNES.

Now, ZSNES used to clear the entire 65536-byte region of SPCRAM. This cleared everything, including the above range. So, for whatever reason, ZSNES starts the SPC700 with the PC set to 0xffc9. That is where the SPC700 tells the CPU it's ready to begin a transfer. It worked before because ZSNES was automatically clearing all RAM to whatever value it did (actually, 0xff now that I look -- which would be incorrect). However, now that range (0x01-0xef) is probably not reset anymore, because the first six opcodes are skipped.
You can fix the problem by setting the SPC700 PC register to 0xffc0 upon reset/power-on, as it should have been from the beginning.

This probably won't fix much, but it is a bug nonetheless.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

byuusan wrote:Sorry, I'll try to be more clear.
Thanks, I think I follow now.
byuusan wrote: We know that upon SNES power-on, SPCRAM is initialized to random values that vary depending on who does the test.
Since when? We've had an init table which was proven to be correct for a while now.
byuusan wrote: Now, ZSNES used to clear the entire 65536-byte region of SPCRAM. This cleared everything, including the above range. So, for whatever reason, ZSNES starts the SPC700 with the PC set to 0xffc9. That is where the SPC700 tells the CPU it's ready to begin a transfer. It worked before because ZSNES was automatically clearing all RAM to whatever value it did (actually, 0xff now that I look -- which would be incorrect).
No.
We init SPCRAM properly on init, and have for a while now.

Code: Select all

void clearSPCRAM()
{
  /*
  SPC RAM is filled with alternating 0x00 and 0xFF for 0x20 bytes.

  Basically the SPCRAM is initialized as follows:
  xx00 - xx1f: $00
  xx20 - xx3f: $ff
  xx40 - xx5f: $00
  xx60 - xx7f: $ff
  xx80 - xx9f: $00
  xxa0 - xxbf: $ff
  xxc0 - xxdf: $00
  xxe0 - xxff: $ff
  */
  unsigned int i;
  for (i = 0; i < 65472; i += 0x40)
  {
    memset(spcRam+i, 0, 0x20);
    memset(spcRam+i+0x20, 0xFF, 0x20);
  }
}
Which is correct, and without this quite a few games bomb out, such as Panic Bomber World.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
byuu

Post by byuu »

What the hell? That's... weird. It was my understanding that the default power-on state was undefined, and thus just random values. Not that I don't trust ZSNES... but can anyone else confirm this?

How could you even check 0x01-0xef, since the IPLROM clears this range before any program can take control? Though I suppose it doesn't matter.
I'll have to try Panic Bomber World on a copier, because I'm quite certain it won't initialize SPCRAM to ... whatever that is you posted.
Not to mention that since SPCRAM isn't cleared on reset... it must be one of those games like Super EDF that check for that or something.

Thanks for the code though, that'll save me a lot of trouble.
We init SPCRAM properly on init, and have for a while now.
I was referring to 1.36. You wanted to know what old versions and new versions do.

On another note, I have another question, this time about apudsp.txt...
All registers are accessed by the SPC700 setting the address in $00F2, then
reading/writing $00F3. Note that the register addresses use only 7 bits:
$80-$ff are read-only mirrors of $00-$7f. Any unspecified registers/bits are
read/write with no known effect.
So then any writes to $80-$ff are ignored? ZSNES doesn't ignore these writes, and games like Zelda 3 attempt to write here. Log:
* DSP write to b0:01
* DSP write to c0:60
* DSP write to 80:60
* DSP write to b0:02
* DSP write to c0:0c
* DSP write to 80:21

Just want to make sure it's correct to ignore these writes.

Also, my faux DSP emulation just keeps a 128-byte buffer that acts as RAM for these values. Will this be sufficient to fake the fact that I don't really have all the DSP stuff (BRR decoding, ADSR/GAIN, pitch, echo, reverb, volume, panning, etc. etc. etc.) in there? Or do the values read back change from what was written to them sometimes when DSP things happen?
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

byuusan wrote:What the hell? That's... weird. It was my understanding that the default power-on state was undefined, and thus just random values. Not that I don't trust ZSNES... but can anyone else confirm this?
It was first discovered by Overload and put into Super Sleuth, then Snes9x and ZSNES copied, at which point Gemfire also became fixed, and then it was copied into SNEeSe too.
byuusan wrote:
We init SPCRAM properly on init, and have for a while now.
I was referring to 1.36. You wanted to know what old versions and new versions do.
That is >3 years old. I don't care for old stuff.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
anomie
Lurker
Posts: 151
Joined: Tue Dec 07, 2004 1:40 am

Post by anomie »

byuusan wrote:Fascinating. Are you going to go through and test all of the opcodes individually and document this behavior? I could give you a hand with a few of them if you like.
Except for MOV and MOVW, everything that writes memory is a read-modify-write operation.
Hm, the best way I can think of emulating this will be to set writes to $fa-$fc to temp_TnTARGET, and then only change the TnTARGET to whatever the temp_ variable is when it actually wraps back to zero via the current TnTARGET value, unless of course you write to TnTARGET when the timer is disabled in $f1 bits 2,1,0.
No, just change TnTARGET immediately. If you set TnTARGET higher then everything works as expected, it's only when you go lower that odd things happen.
But if you say my code's good, I trust that a lot more than the results from... well, you get the idea ;)
Well, i haven't *tested* your code, it just looks ok ;)
byuusan wrote:So then any writes to $80-$ff are ignored?
Exactly. For example, in my test ROM i write to $4C and i get sounds. I write the same thing to $CC and I get nothing. random tests on other registers give similar lacks of effect.
Or do the values read back change from what was written to them sometimes when DSP things happen?
VxENVX, VxOUTX, and ENDX change based on the DSP state. Also, if the echo buffer is enabled then the appropriate area of RAM will have echo data written to it.
-_pentium5.1_-
Lurker
Posts: 110
Joined: Sat Sep 04, 2004 7:55 pm
Location: USA

Post by -_pentium5.1_- »

byuusan wrote: I'll have to try Panic Bomber World on a copier, because I'm quite certain it won't initialize SPCRAM to ... whatever that is you posted.
Panic Bomber World uses the SA-1 chip, so it won't work on a copier. I know there's a cracked ROM of Panic Bomber World, but I don't know what it's for. (The cracked ROM gives a copy-protection error on current emulators; you should use the good ROM anyway. Since this game can't be tested on a copier, maybe compare the behavior to Super Sleuth? Or disassemble it and write a test program to suit?)
This signature intentionally contains no text other than this sentence.
byuu

Post by byuu »

Well that ruins it, indeed.

I'm still not convinced RAM is initialized like that. It makes no sense to force the hardware to do something like that. I'll write my own test program to read the contents of SPCRAM and transfer it to SRAM. Hopefully the copier BIOS doesn't overwrite all 64k of SPCRAM before I get access to it, but even a page or two would be enough to verify what Nach mentioned.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

You can test Gemfire on a copier.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
Overload
Hazed
Posts: 70
Joined: Sat Sep 18, 2004 12:47 am
Location: Australia
Contact:

Post by Overload »

byuusan wrote:Well that ruins it, indeed.

I'm still not convinced RAM is initialized like that. It makes no sense to force the hardware to do something like that. I'll write my own test program to read the contents of SPCRAM and transfer it to SRAM. Hopefully the copier BIOS doesn't overwrite all 64k of SPCRAM before I get access to it, but even a page or two would be enough to verify what Nach mentioned.
It differs between machines. My Japanese Machine (SN# 15722371) doesn't initialize SPCRAM but PAL Machine does.

This is the test program that i wrote (~2 years ago).

http://users.tpg.com.au/trauma/temp/spchack.zip
I included the sram from my jap (GD3) and pal machine (SWC)

It would be nice to have someone with an American Machine to also run the program to see what it gives.
byuu

Post by byuu »

Yeah, and if it differs per-machine, then it's not a good idea to make an emulator assume you're running a specific type of machine -- at least not without an option to select the machine you want to emulate. If it weren't for debugging purposes, I'd probably initialize all RAM to rand() at startup. It would help prevent PD ROMs that rely on RAM being a specific value, like Qwertie's stuff.

Your PAL SRAM file looks to have program code in the first 0x3000 bytes or so before that pattern begins (obviously used by the copier BIOS). How sure are you that it isn't that program that's initializing everything else to 0xff/0x00? Keeping in mind how SPC700 programs just love to rewrite themselves whilst running, just disassembling it probably isn' sufficient. This would probably be best tested with a flash cart...

I have reservations that a special program/chip exists on the SNES to manually set RAM/SPCRAM to any particular value on power on. Whatever pattern you're seeing could easily just be various fluctuations based on whatever RAM chips do when first given power.

Oh, and thanks for the code. I only have two Japanese units though, so I'm afraid I can't help you there.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

byuusan wrote:Yeah, and if it differs per-machine, then it's not a good idea to make an emulator assume you're running a specific type of machine -- at least not without an option to select the machine you want to emulate.
If it just differs on Japanse vs. US and Europe, it should be init'd via the country detected of the ROM you're loading.
byuusan wrote: If it weren't for debugging purposes, I'd probably initialize all RAM to rand() at startup. It would help prevent PD ROMs that rely on RAM being a specific value, like Qwertie's stuff.
You'll break real games too like Gemfire and Panic Bomber World.

Overload:
If you're saying Japanese games don't need to rely on a specific initlization, how do you explain the init fixed PBW?
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
Overload
Hazed
Posts: 70
Joined: Sat Sep 18, 2004 12:47 am
Location: Australia
Contact:

Post by Overload »

byuusan wrote:Your PAL SRAM file looks to have program code in the first 0x3000 bytes or so before that pattern begins (obviously used by the copier BIOS). How sure are you that it isn't that program that's initializing everything else to 0xff/0x00? Keeping in mind how SPC700 programs just love to rewrite themselves whilst running, just disassembling it probably isn' sufficient. This would probably be best tested with a flash cart...

I have reservations that a special program/chip exists on the SNES to manually set RAM/SPCRAM to any particular value on power on. Whatever pattern you're seeing could easily just be various fluctuations based on whatever RAM chips do when first given power.
If you disable sound on the SWC it doesn't transfer any code to SPCRAM. This did work on my copier 2 years ago but unfortunately the NVRAM doesn't work anymore, so once you switch off the SWC it doesn't save the settings anymore. You can also get your hands on the 'Super Wildcard DX2 BIOS' and test in your emulator.

I see no reason why this pattern could be set at init. Remember there are two APU versions, maybe the japanese machines that we have the first version whereas my PAL machine might have version 2.
Overload
Hazed
Posts: 70
Joined: Sat Sep 18, 2004 12:47 am
Location: Australia
Contact:

Post by Overload »

Nach wrote:Overload:
If you're saying Japanese games don't need to rely on a specific initlization, how do you explain the init fixed PBW?
I don't know.

[Edit]
Super Battleship (U) is another game that breaks if you don't initalize spcram. Try this on your japanese machine.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

Okay, that's 3 games we know needs init then.
We really should keep a list of stuff like this somewhere...

I guess it's possible for US developers to overlook this since they're testing on US hardware, which explains for Gemfire and Super Battleship. But what exactly happened with the Japanese release Panic Bomber World? Could it be later SFCs do init and that's what it was tested on, and no one tried it on an earlier one or complained for there to be a R1.1? Or perhaps the SA-1 does initing?
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
byuu

Post by byuu »

It could just be any random thing that results in PBW working. Maybe an opcode has a wrapping bug and it just happens to read the 0x00 you set, whereas before it was getting 0xff which caused the code to crash? Perhaps Japanese systems don't initialize SPCRAM, but they still end up with certain values in certain spots that just makes the game work? Perhaps it's because that bug I mentioned above about starting the SPC at 0xffc9 was responsible?

I'll try and tear apart the code from Gemfire/Super Battleship and see what I find. I wonder what you'd even take advantage of by assuming the RAM is striped at poweron. I guess the easy way would to be to do a tracelog of SPC700 commands with RAM initialized and with it not. I should be able to spot the first difference pretty easily that way. Hopefully my POS SPC700 code will run either game yet :/
I also assume that all of these games have handlers for when you reset the game, like Super EDF, otherwise its own changes to RAM could break itself.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

byuusan wrote:It could just be any random thing that results in PBW working. Maybe an opcode has a wrapping bug and it just happens to read the 0x00 you set, whereas before it was getting 0xff which caused the code to crash? Perhaps Japanese systems don't initialize SPCRAM, but they still end up with certain values in certain spots that just makes the game work? Perhaps it's because that bug I mentioned above about starting the SPC at 0xffc9 was responsible?
It just happens to work in 3 different games???

And we're not just talking in ZSNES here, the exact same problems were in Snes9x too till we did the RAM init there.

There were also some hacks we found were no longer needed which hacked SPC RAM for certain games, perhaps it would be an idea to look into them to see if the RAM init fixed those as well.

Based on the evidence, I don't think it just happens to work, or see how what ZSNES did regarding starting the SPC was related to Snes9x.

Would have to talk to TRAC, but I'm pretty sure he said when he did the init, it fixed Gemfire for him too.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
byuu

Post by byuu »

It just happens to work in 3 different games???
The other two were PAL/US games. You asked why the Japanese game worked if the Japanese unit didn't initialize SPCRAM. I was just offering wild guesses, anyway.
Post Reply