All Codemasters' games have auto-detect region feature and so they can be played on both NTSC and PAL consoles. Also, most games are working on Dendy (Famiclones) too, except:
*Bee 52
*Quatro Sports: Pro Tennis
*Quattro Arcade: CJ, Stunt Buggies
Those games, when run on Famiclone (Dendy) hangs momentally. Do you have any idea how to fix them?
The auto detect code needs to be forced to NTSC mode, or else detect Dendy PAL mode as a third possibility and then use NTSC timing.
Thank you, problem solved (CodeMasters' PAL/NTSC checking routine was counting CPU cycles between two VBLANKs and it was only prepared for two distinct values - one for PAL and one for NTSC. When it occured any other value, it was forced to count CPU cycles again. So for Dendy, it went into infinite loop.
How big is the routine? Can it be replaced with
mine, which returns one of three values (NTSC, PAL NES, or Dendy)?
Code:
03:CA26:2C 02 20 BIT $2002 = #$00
03:CA29:30 FB BMI $CA26
03:CA2B:A2 00 LDX #$00
03:CA2D:A0 00 LDY #$00
03:CA2F:E8 INX
03:CA30:D0 01 BNE $CA33
03:CA32:C8 INY
03:CA33:2C 02 20 BIT $2002 = #$00
03:CA36:10 F7 BPL $CA2F
03:CA38:8E 00 02 STX $0200 = #$B0
03:CA3B:8C 01 02 STY $0201 = #$09
03:CA3E:AD FE 07 LDA $07FE = #$00
03:CA41:29 BF AND #$BF
03:CA43:C0 09 CPY #$09 ;NTSC?
03:CA45:F0 06 BEQ $CA4D
03:CA47:C0 0A CPY #$0A ;PAL?
03:CA49:D0 D8 BNE $CA23
03:CA4B:09 40 ORA #$40
>03:CA4D:8D FE 07 STA $07FE = #$00
03:CA23:20 9C C9 JSR $C99C
>03:C99C:2C 02 20 BIT $2002 = #$00
03:C99F:30 FB BMI $C99C
03:C9A1:2C 02 20 BIT $2002 = #$00
03:C9A4:10 FB BPL $C9A1
03:C9A6:60 RTS
It looks like it'd fit size-wise. But what does their NMI handler look like when not much is going on? Because my detection code waits for the NMI handler to modify a variable in zero page and counts how long it takes for the variable to change again.
This routine is executed only once, at startup and then game uses $07FE to determine if its NTSC ($0) or PAL ($40)
I personally prefer a console detection routine that doesn't rely on NMIs. It's less invasive, and counting the expected amount of cycles and then testing for vblank works just as well comparing the cycle count against expected values once vblank hits.
EDIT: One way to do it is: after waiting for vblank by polling $2002, wait enough cycles for the next NTSC vblank and test $2002. If the vblank flag is set, it's an NTSC console, if not, wait a little more for the PAL vblank and test $2002 again. If the flag is set, then it's a PAL console, if not, it must be Dendy, but you can wait a little longer to test the vblank flag again just to be sure.
I don't actually make this clear distinction between console types though, since Dendy has some things similar to PAL and others similar to NTSC, so I actually set 2 flags in my detection routine: one for the frame rate 50Hz vs. 60Hz) and another for vblank length (20 scanlines vs. 70 scanlines). The frame rate can be used to control the speed of the game and the music, while the vblank length can be used to control VRAM updates and music pitch, for example.
You have a point. I thought explicitly testing for a breakpoint between 29780 and 33247 cycles and another between 33247 and 35464 cycles would take more ROM space. But for poops and giggles, I tried writing a routine like what you recommend. It turns out that because the test takes long enough that the PPU stabilizes, the waiting code can be removed from the hardware init routine, making up the lost bytes.
I succeded in fixing most of those games just by forcing the check routine to return NTSC when in Dendy Mode.
One game that cause troubles is Fire Hawk. The title screen shakes in Dendy Mode (in PAL and NTSC is stable) and the game after starting crashes immediatelly due to sprite 0 hit fail.
Anyone has idea why the shaking appears?
Dendy / NTSC
Fire Hawk uses DPCM Split, and if it just lets the timer free-run rather than resynchronizing every frame, it may not be properly accounting for the extra 50 post-render lines.