Search code examples
cassembly6502nes

Is there a bug in the nestest rom?


I am currently making an emulator for the NES (like many others) , and while testing my emulation against the nestest rom by Kevtris (found here : https://wiki.nesdev.com/w/index.php/Emulator_tests), there is a weird bug I've encountered , at the instruction 877 on the nestest log (this one : http://www.qmtpro.com/~nes/misc/nestest.log , at line CE42) .

The instruction is a PLA , which pulls the accumulator from the stack , while having the stack pointer at $7E at the beginning. (I'm using a 1 byte value for the stack pointer , since it goes from 0x0100 to 0x01FF , so when I write $7E talking about the stack , it's 0x017E , not zeropage ;) )

So , when PLA is executed at line 877, the stack pointer moves to $7F and retrieve the first byte and store into the accumulator .

The problem is here : on the nestest log , this byte is 0x39 , then , on instruction 878 which is also a PLA , the retrieved byte at $80 (stack pointer incremented + 1) , is 0xCE, and this has inverted the low byte and high byte.

The values written on the stack (0xCE39) have their origin in the JSR instruction at line CE37 and here is my implementation of the JSR opcode :

uint8_t JSR(){
   get() ; // fetch the data of the opcode , like an absolute address operand or a value
   uint16_t newPC = PC - 1 ; // the program counter is decremented by 1
   uint8_t low = newPC & 0x00FF ; 
   uint8_t high = (newPC & 0xFF00) >> 8; 
   write_to_stack(SP-- , low) ; //we store the PC , highest address in stack takes the low bytes
   write_to_stack(SP-- , high) ; //lower address on the stack takes the high bytes 
   PC = new_address ; // the address we read that points to the subroutine. 
   return 0 ; 
}

Here are the logs from nestest :

CE37  20 3D CE  JSR $CE3D                       A:69 X:80 Y:01 P:A5 SP:80 PPU:233, 17 CYC:2017
CE3D  BA        TSX                             A:69 X:80 Y:01 P:A5 SP:7E PPU:251, 17 CYC:2023
CE3E  E0 7E     CPX #$7E                        A:69 X:7E Y:01 P:25 SP:7E PPU:257, 17 CYC:2025
CE40  D0 19     BNE $CE5B                       A:69 X:7E Y:01 P:27 SP:7E PPU:263, 17 CYC:2027
CE42  68        PLA                             A:69 X:7E Y:01 P:27 SP:7E PPU:269, 17 CYC:2029
CE43  68        PLA                             A:39 X:7E Y:01 P:25 SP:7F PPU:281, 17 CYC:2033
CE44  BA        TSX                             A:CE X:7E Y:01 P:A5 SP:80 PPU:293, 17 CYC:2037

With my code , I am having 0xCE at $7F and 0x39 at $80. So the first PLA with my code stores 0xCE in the accumulator , and the second PLA stores 0x39, and this is the invert of what the nestest log shows.

I don't know if my JSR code is wrong , it has succeeded until now. I tried inverting the low and high byte of the program counter when stored on the stack , but , as expected , the instructions become invalid at the first JSR of the rom .

So , what do you guys think I'm missing ?


Solution

  • The mistake is not in nestest; the mistake is in your implementation of JSR and RTS!

    You need to push the high byte first, and then the low byte. (This is so that the low byte can be retrieved first, and incremented while the high byte is being fetched)