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 ?
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)