gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > GBA Emulator Discrepencies

#24187 - wlan - Thu Jul 29, 2004 10:46 am

I've written a few programs for the GBA and I can't figure out why this is: the programs work on GBA, but they do not work on every emulator.

What confuses me even more is that they work flawlessly on actual hardware, yet sometimes weird bugs will surface on emulation. Is this something I should be very concerned about? I like to believe I am fairly thorough with tracking bugs but could there be some lurking there that show up on emulation and not on GBA?

I've even had some abnormal effects with the same emulator but on different machines. I use VBA exclusively and so if it works on that and hardware I am satisfied, but my previous experiences have left me uncertain.

Can anyone clear this issue up? Is it a great cause for worry?

#24192 - torne - Thu Jul 29, 2004 12:40 pm

The emulators aren't accurate. That's basically it. =)

If you have a 'bug' that only shows up on an emu and not on hardware, then it's not a bug in your code, it's a bug in the emulator.

At a guess, the large majority of people who play homebrew games have the required hardware to play them on a real GBA, so personally I wouldn't worry. There are now a number of commercial carts that don't work on emulators but work flawlessly on hardware - the GBA videos.

#24194 - yaustar - Thu Jul 29, 2004 3:13 pm

I had a case of the reverse where the tiles of a background showed up fine in the emu but not on the hardware.
_________________
[Blog] [Portfolio]

#24201 - torne - Thu Jul 29, 2004 5:01 pm

If it works on an emu but not on hardware then both your code and the emulator have a bug. =)

#24205 - tepples - Thu Jul 29, 2004 5:40 pm

If you can produce different behavior on the GBA and on an emulator, then first reduce your program to the minimal test case the reproduces the bug. From here, the road splits:

The Way of the White Robe and Halo

Report the bug to the maintainer, attaching your test case to the bug report. I've done this for several layout bugs in Mozilla and for a few emulation bugs in VBA, such as this.

The Way of the Red Suit and Horns

If your test case produces effects that the program can detect from within the emulation, then turn that test case into a library, and call it from each program you publish. Then have your programs put up a message and halt if run under such emulation. I recommend this approach for dealing with bugs in no longer maintained emulators. In fact, I've done this for some of my NES programs that refuse to run under the outdated NESticle emulator, directing players to a better NES emulator.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#24267 - sgeos - Sat Jul 31, 2004 6:09 am

Does your code run under no$gba? You might want to try a no$gba bug count just for fun.

-Brendan

#24308 - caitsith2 - Sun Aug 01, 2004 6:10 am

tepples wrote:

The Way of the Red Suit and Horns

If your test case produces effects that the program can detect from within the emulation, then turn that test case into a library, and call it from each program you publish. Then have your programs put up a message and halt if run under such emulation. I recommend this approach for dealing with bugs in no longer maintained emulators. In fact, I've done this for some of my NES programs that refuse to run under the outdated NESticle emulator, directing players to a better NES emulator.


Nintendo seems to have used this method with their nes classics. Most emulators that auto detect the save type by the specific read/write behaviour, will not run any of the nes classics, because nintendo's detection library does a write of [Low byte of Sram Address] to [Sram Address], and reads it back, and compares the readback to what was written. If all 65536 test cases come back as positive, then there is no accident as far as sram being present is concerned.

Im surprised nintendo hasn't yet used this with sram / flash save types yet. For sram save types, all they have to do is these steps.

1. Write to 0x5555, with 0xAA, (and never use that location for anything else ever.)
2. Read 0x0000.
3. Increment the value and write it back to 0x0000.
4. Read 0x0000, and compare it with the written back value. If the read value is the same as the written value, then sram is presnet, however, if the value differs, then either the flash / eeprom save type is present, or nothing is hardwired.


For the second test concerning saveram, to detect emulation at this point, is taking advantage of the fact that nearly all written games using sram are only using 256Kbit sram. Well, some emulators, like VBA allocate 512Kbit, instead of mirroring the 256Kbit present in most games, which can be detected.

1. Read 0x0000 (only if you wish to back up its contents.) and 0x8000 (only if dealing with 512Kbit sram)
2. a. If 256 Kbit, increment the value and write it to 0x8000.
b. If 512 Kbit, increment the value, and write it to 0x0000. Increment it once more, and write it to 0x8000.
3. Now compare 0x0000 with 0x8000. If they are equal, then only 256Kbit is wired in. If they are not equal, then the full 512Kbit is present.

For the flash save type, detect emulator with these steps.

1. Read 0x0000. (not to back it up, but to gurantee that the written value WILL be different.)
2. Increment the value, and write it back.
3. Read the value. If the value is the same as before, then flash may be present, call whatever routine you use at this point to detect if flash actually is present, based on manufacturer/device ID codes.

Finally, nintendo could even throw the detect save by string off, by implementing these routines, but actually use the flash backup library to detect the flash, if sram is present, or the sram backup library, to do the sram detection, if flash is present, or even better, just make a call to the function in dummy library, in such a way, that the call never gets executed.

Also, while we are on emulator detection, The trick that the demotronic trick uses to detect emulation, is the write some known value to channel 3 wave ram, turn on the channel, for long enough to play about 4-5 samples, then turn the channel off, and read back the wave ram. If the read back waveram is 100% verbatim to the written wave ram, then it is definitely an emulator. Seems nintendo never found about that trick and used it either.

#24347 - dagamer34 - Sun Aug 01, 2004 9:38 pm

I've really been wondering why no$GBA emulates vertical mosaic but not horizontal mosaic. I tested it with some code just to make sure and that how it was. Weird to support only half of a PPU operation like that...
_________________
Little kids and Playstation 2's don't mix. :(

#25503 - wlan - Tue Aug 24, 2004 4:29 am

Thanks for all the great replies.

sgeos wrote:
Does your code run under no$gba? You might want to try a no$gba bug count just for fun.

-Brendan


It runs alright under No$.

I checked out the bug count and was more or less confused. When I run the game code on no$ with krawall functions commented out I get no errors. When I run the game code on no$ with krawall enabled I get no less than ~16,000 errors a second (still runs fine though). Either way it has always worked without problems on the GBA hardware, but I wonder why I get these results. I'll look into how I'm handling krams and such, since its possible I'm doing it improperly.

I might have found an instance where no$ is not emulating properly. In my game initialization routine I tryed enabling interrupts (timer, vblank) *before* I enabled the rest of my game classes (including krawall) and no$ would not run the ROM. Since my vblank interrupt calls these instances that weren't initialized that makes sense right? However on the GBA hardware this same code would run fine. I'm not saying that makes it fine - its flat out wrong - but I figured that if he is going for 100% emulation, it would still run on no$.

edit-
Maybe the flashing software behaves differently than a real ROM.

#26046 - Quirky - Sat Sep 04, 2004 9:52 pm

wlan wrote:
I checked out the bug count and was more or less confused. When I run the game code on no$ with krawall functions commented out I get no errors. When I run the game code on no$ with krawall enabled I get no less than ~16,000 errors a second (still runs fine though).


That is ( probably ) down to illegal unaligned reads/writes in krawall. Most of the time it's so you can read "address[offset<<shift]" in one instuction, which may not be an aligned address. if you loaded a byte (ldrb) then you can't use the shift thingy. Uuf. Here's what I mean:

ldr r0,[r1, r2,lsl#2]

This may give "buggy" read in no$gba if r1 isn't aligned (a multiple of 4) as you shouldn't read 4 bytes from an unaligned address. It doesn't seem to do any harm though in real life.

ldrb r0,[r1, r2,lsl#2]
This is actually a syntactically illegal instruction, you can't do funky shifts on byte/half word read/writes, but if it were correct, it wouldn't give an illegal read error.

The "correct" way, which solves the unaligned read bug but requires 2 instructions and blitzs a register would be:
mov r2,r2,lsl#2
ldrb r0,[r1, r2]


(instead of ldrb, it could be ldrh, strb,strh)

Of course it could be a different bug, such as reading from an illegal address (uninitialised/random value) or something similar.

#26047 - tepples - Sat Sep 04, 2004 10:17 pm

Quirky wrote:
Most of the time it's so you can read "address[offset<<shift]" in one instuction, which may not be an aligned address. if you loaded a byte (ldrb) then you can't use the shift thingy. Uuf. Here's what I mean:

ldr r0,[r1, r2,lsl#2]

[snip]

The "correct" way, which solves the unaligned read bug but requires 2 instructions and blitzs a register would be:
mov r2,r2,lsl#2
ldrb r0,[r1, r2]

You need two instructions with the shift thingy way as well, because don't you need to AND off the high bits?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#26055 - DKL - Sun Sep 05, 2004 2:54 pm

Quirky wrote:
ldrb r0,[r1, r2,lsl#2]
This is actually a syntactically illegal instruction,


"ldrb r0,[r1, r2,lsl#2]" IS a legal instruction, as well as ldr.
Only "ldrh r0,[r1, r2,lsl#2]" would not.

DKL

#26064 - FluBBa - Mon Sep 06, 2004 10:39 am

Maybe he thought of lrdsb which has the same limitations as lrdh (I think)?
_________________
I probably suck, my not is a programmer.

#26065 - DKL - Mon Sep 06, 2004 11:25 am

FluBBa wrote:
Maybe he thought of lrdsb which has the same limitations as lrdh (I think)?

[Off_Topic]
Hep Flubba, do you know what happened to PIRACY-DOT-COM?
[/Off_Topic]

DKL

#26083 - FluBBa - Tue Sep 07, 2004 12:05 pm

Nope, no idea actually.
Hopefully it doesn't have anything to do with Nintendo, I've seen 2 other websites dissapear just recently (which might have to do with Nintendo being pissed).
But I'm probably just paranoid.
_________________
I probably suck, my not is a programmer.