Gameboy Development Forum

Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)

You are not logged in.

Ads

#1 2021-02-19 00:41:00

densming
New member
Registered: 2021-02-19
Posts: 5

Blargg's Test ROMs

Hi all,

  I'm writing a GB emulator in Swift, and running Blargg's test ROMs.  I don't have PPU written yet, so I'm looking at the results of the test over the serial connection.  For some of the tests, instead of getting a "Failed" message, I'm getting stuff like the following:

;> ?> @= @> :< <; 9= <; 9> 9>

Does anyone know what this means or how to interpret this?  (This is from the 11-op a,(hl).gb rom, but other ROMs give similar output).

Thanks
densming

Offline

 

#2 2021-02-19 01:30:28

nitro2k01
Administrator
Registered: 2008-02-22
Posts: 249

Re: Blargg's Test ROMs

Hi. When a test fails, the test prints a bunch for numbers with diagnostic information before it prints "Failed". If you wait long enough (assuming your emulation is good enough to run the test to completion) you should see "Failed" eventually. Normally, the debug numbers are hex numbers. I would first suspect that something goes wrong in the test's hex conversion function. It looks like this:

Code:

; Prints A as two hex chars and updates checksum
; Preserved: BC, DE, HL
print_hex:
     call update_crc
print_hex_nocrc:
     push af
     swap a
     call +
     pop  af
     
+    and  $0F
     cp   10
     jr   c,+
     add  7
+    add  '0'
     jp   print_char_nocrc

If you look at what the garbage characters are, it turns out that they are the ASCII characters directly following 9. (See for example ASCIItable.com for a quick ASCII reference.) This pretty much narrows down the problem to two instructions, and the carry flag in particular: cp xx and jr c,xx.

For example:
cp xx doesn't set the carry flag correctly.
cp xx inverts it from its real value.
jr c, xx always jumps.
jr c, xx only if c is not set (ie the inverse of what it should do).

Btw, Blargg's tests are designed to be useful for emulation development. For this reason, the values written to VRAM are mapped to the corresponding ASCII values. So if you place RAM on $8000-$9FFF, you can just dump $9800-$9BFF as ASCII characters to the console to see the current log output. (Though that wouldn't help in this case since that data would have the same corruption discussed above.) (Or, more like print (value & 0x7F) because there's a second set of characters with inverted colors which are mapped to the corresponding ASCII value but with bit 7 set.)


Blog: Gameboy Genius
"A journey of a thousand miles begins with one small step"
Old Chinese Proverb

Offline

 

#3 2021-02-19 01:56:01

densming
New member
Registered: 2021-02-19
Posts: 5

Re: Blargg's Test ROMs

Thanks for the reply.  I think I have my carry/halfcarry working properly but I'm not positive.  Here's what I have for the CP operations (this is for CP E but they all work similarly):

        case 0xBB:    // CP E
            flag_h = half_carry(a, -e)
            flag_c = carry(a, -e)
            flag_z = (a == e)
            flag_n = true
            cycles = 1

The half_carry method is:
    func half_carry(_ x: Int, _ y: Int) -> Bool {
        return (((x & 0x0F) + (y & 0x0F)) & 0xF0) > 0
    }

And carry:   
    func carry(_ x: Int, _ y: Int) -> Bool {
        return (((x & 0xFF) + (y & 0xFF)) & 0x0F00) > 0
    }

Does this look right?

Offline

 

#4 2021-02-19 03:05:20

nitro2k01
Administrator
Registered: 2008-02-22
Posts: 249

Re: Blargg's Test ROMs

That does not look right. You are too eager in you bit masking, which makes carry fail for sub/cp. Consider the trivial example of A==0, and executing cp 1. This should set carry. c gets set to carry(0,-1).

Now follow the execution:
(x & 0xFF) == 0
(y & 0xFF) == (-1 & 0xFF) == 0xFF
0xFF & 0x0F00 == 0 which is not greater than 0 and c gets cleared (incorrectly). Rethink your carry function, or maybe have a separate carry function for sub/cp.


Blog: Gameboy Genius
"A journey of a thousand miles begins with one small step"
Old Chinese Proverb

Offline

 

#5 2021-02-19 18:03:20

densming
New member
Registered: 2021-02-19
Posts: 5

Re: Blargg's Test ROMs

Thanks for setting me on the right track!  I fixed all the errors and now the test rom passes!  All of the blargg ROMs pass now except for 01-special, 02-interrupts, and 08-misc instrs.  Curiously, the 08-misc instrs ROM fails with a code "F1", which is the POP AF instruction.  It should be straightforward so I don't know what's going on with it.  All the POP opcodes are similar, so I suspect they all have whatever this problem is.

        case 0xF1:    // POP AF
            af = read16(sp)
            sp = (sp + 2) & 0xFFFF
            cycles = 3

read16() reads the low byte first, followed by the high byte like it's supposed to.

Offline

 

#6 2021-02-20 00:56:32

nitro2k01
Administrator
Registered: 2008-02-22
Posts: 249

Re: Blargg's Test ROMs

If you've got the byte order right, your problem is probably that you're not masking the flag bits. The lower 4 bits of F are always zero. (Or put differently, those bits don't exist but are written as zero when you push AF.) So in push AF try masking like this:

Code:

            sp = (sp - 2) & 0xFFFF
            write16(sp, af & 0xFFF0)

Also, word from the wise: if you're planning to make the emulator cycle accurate, you want to perform push/pop as two separate writes, forward the clock and have some sort of planning on how to process events in the middle of an instruction. Consider the following:

You push/pop in VRAM, and VRAM goes from being accessible to inaccessible in the middle of the instruction.

You have SP set to for example IO register space ($FF00-$FF7F) or ROM in one of the MBC regs and push/pop. Which byte gets read/written first and what effect does it have?

These are things that most games don't do, certainly not deliberately, but there sure are test ROMs to call them out, and they might theoretically matter for situations where a game is buggy and crashes in on case and doesn't in the other.


Blog: Gameboy Genius
"A journey of a thousand miles begins with one small step"
Old Chinese Proverb

Offline

 

#7 2021-02-21 11:37:17

densming
New member
Registered: 2021-02-19
Posts: 5

Re: Blargg's Test ROMs

Thanks for the help! I'll try out the F register suggestion you mentioned.

  As far as the write16 being two separate writes - I'll consider this, too.  I'm not looking for my emulator to run every game and be completely bug free.  I'm doing it mainly as a challenge just to see if I can get even one game to run (Super Mario Land is my goal, or Tetris).  If I can do that I'll be happy.  Hopefully official games don't do the kind of trickery you mentioned (at least not intentionally).

Last edited by densming (2021-02-21 11:37:34)

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson