Issue on Indirect,X addressing mode on nestest

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
Concurser
Posts: 8
Joined: Fri Mar 06, 2020 12:30 pm

Issue on Indirect,X addressing mode on nestest

Post by Concurser » Wed Aug 19, 2020 2:02 pm

Hello folks, could someone give a look?

I guess the ram values may be wrong or my (indirect,x) calculation on CFDB A1 80 - LDA ($80, X) is wrong.

I am using nestest rom with a simplified dump log (no PPU etc.)

address space contents before instruction:
mem[0] = 0x04
mem[1] = 0xff
...
mem[511] = 0xA5 //guess this is the data source to be put on the Accumulator, I inserted a small trap on the poke() method to get it...outputs
"Suspect mem write: ADDR=1ff, VAL=5a, PC=cfc7, CYC=2523"

pseudo-code:

Code: Select all

operand = peekByte(...) //returns 0x80
addresslo = 0xFF & (Xreg + operand);
addresshi = peekWord(X_REG + 1); //returns ‭0xFF04‬
address = addresshi + addresslo; //returns 0xFF84...way far from 0x200 (mem[511])
ACCUMULATOR = peekByte(address); //returns 0x3A (mirrroed ROM data from $8000-$BFFF) and not 0x5A as expected
Nestest dump below (left is my emu, right is nestest dump):

Code: Select all

rget: CFDD  C9 5A    CMP A:5A X:00 Y:69 P:25 SP:FB CYC:2553
***CONTEXT INFO (LAST 10 OPCODES)***
Source: CFC7  8D 00 02 STA A:5A X:55 Y:69 P:25 SP:FB CYC:2523	 Target: CFC7  8D 00 02 STA A:5A X:55 Y:69 P:25 SP:FB CYC:2523
Source: CFCA  A9 5B    LDA A:5A X:55 Y:69 P:25 SP:FB CYC:2527	 Target: CFCA  A9 5B    LDA A:5A X:55 Y:69 P:25 SP:FB CYC:2527
Source: CFCC  8D 00 03 STA A:5B X:55 Y:69 P:25 SP:FB CYC:2529	 Target: CFCC  8D 00 03 STA A:5B X:55 Y:69 P:25 SP:FB CYC:2529
Source: CFCF  A9 5C    LDA A:5B X:55 Y:69 P:25 SP:FB CYC:2533	 Target: CFCF  A9 5C    LDA A:5B X:55 Y:69 P:25 SP:FB CYC:2533
Source: CFD1  8D 03 03 STA A:5C X:55 Y:69 P:25 SP:FB CYC:2535	 Target: CFD1  8D 03 03 STA A:5C X:55 Y:69 P:25 SP:FB CYC:2535
Source: CFD4  A9 5D    LDA A:5C X:55 Y:69 P:25 SP:FB CYC:2539	 Target: CFD4  A9 5D    LDA A:5C X:55 Y:69 P:25 SP:FB CYC:2539
Source: CFD6  8D 00 04 STA A:5D X:55 Y:69 P:25 SP:FB CYC:2541	 Target: CFD6  8D 00 04 STA A:5D X:55 Y:69 P:25 SP:FB CYC:2541
Source: CFD9  A2 00    LDX A:5D X:55 Y:69 P:25 SP:FB CYC:2545	 Target: CFD9  A2 00    LDX A:5D X:55 Y:69 P:25 SP:FB CYC:2545
Source: CFDB  A1 80    LDA A:5D X:00 Y:69 P:27 SP:FB CYC:2547	 Target: CFDB  A1 80    LDA A:5D X:00 Y:69 P:27 SP:FB CYC:2547
Source: CFDD  C9 5A    CMP A:3A X:00 Y:69 P:25 SP:FB CYC:2553	 Target: CFDD  C9 5A    CMP A:5A X:00 Y:69 P:25 SP:FB CYC:2553
***OPCODE MISMATCH***
***Written 1088 opcode & CPU status lines.***

Any ideas?

lidnariq
Posts: 9655
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Issue on Indirect,X addressing mode on nestest

Post by lidnariq » Wed Aug 19, 2020 2:09 pm

(zpg,X) reads the word from [zpg+X]. It's not the same as (zpg),y which is what you've implemented here.

User avatar
Quietust
Posts: 1596
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: Issue on Indirect,X addressing mode on nestest

Post by Quietust » Wed Aug 19, 2020 2:19 pm

Concurser wrote:
Wed Aug 19, 2020 2:02 pm

Code: Select all

operand = peekByte(...) //returns 0x80
addresslo = 0xFF & (Xreg + operand);
addresshi = peekWord(X_REG + 1); //returns ‭0xFF04‬
address = addresshi + addresslo; //returns 0xFF84...way far from 0x200 (mem[511])
ACCUMULATOR = peekByte(address); //returns 0x3A (mirrroed ROM data from $8000-$BFFF) and not 0x5A as expected
That logic is incorrect - it should read as follows:

Code: Select all

operand = peekByte(PC++);
addresslo = peekByte(0xFF & (Xreg + operand));
addresshi = peekByte(0xFF & (Xreg + operand + 1));
address = (addresshi << 8) | addresslo;
ACCUMULATOR = peekByte(address);
And if you want to be really specific, there should be an additional "peekByte(operand);" immediately after fetching the operand (which costs an extra CPU cycle).
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

Concurser
Posts: 8
Joined: Fri Mar 06, 2020 12:30 pm

Re: Issue on Indirect,X addressing mode on nestest

Post by Concurser » Thu Aug 20, 2020 9:08 am

Thanks, a few opcodes later I sorted out another trick on 0-page page wrap when dealing with the LDA ($FF,X) situation.

Now I found something interesting that is a possible LDA absolute bug that I can´t figure out the root issue.

Please check below, Accumulator is loaded with contents from absolute data from 0x0200.

Strangely, Nestest expects AA while I have 5A on A.

Code: Select all

Source: D01C  AD 00 02 LDA A:AD X:00 Y:69 P:A5 SP:FB CYC:2650  Target: D01C  AD 00 02 LDA A:AD X:00 Y:69 P:A5 SP:FB CYC:2650
Source: D01F  C9 AA    CMP A:5A X:00 Y:69 P:25 SP:FB CYC:2654	 Target: D01F  C9 AA    CMP A:AA X:00 Y:69 P:A5 SP:FB CYC:2654
Only time 0x0200 is written before that, it gets 5A!
Suspect mem write: ADDR=1ff, VAL=5a, PC=cfc7, CYC=2523

Sorry, sometimes I need some peer reviewing to rethink the code, thats why I come back to this forum.

User avatar
Quietust
Posts: 1596
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: Issue on Indirect,X addressing mode on nestest

Post by Quietust » Thu Aug 20, 2020 9:24 am

Concurser wrote:
Thu Aug 20, 2020 9:08 am
Thanks, a few opcodes later I sorted out another trick on 0-page page wrap when dealing with the LDA ($FF,X) situation.

Now I found something interesting that is a possible LDA absolute bug that I can´t figure out the root issue.

Please check below, Accumulator is loaded with contents from absolute data from 0x0200.

Strangely, Nestest expects AA while I have 5A on A.

Code: Select all

Source: D01C  AD 00 02 LDA A:AD X:00 Y:69 P:A5 SP:FB CYC:2650  Target: D01C  AD 00 02 LDA A:AD X:00 Y:69 P:A5 SP:FB CYC:2650
Source: D01F  C9 AA    CMP A:5A X:00 Y:69 P:25 SP:FB CYC:2654	 Target: D01F  C9 AA    CMP A:AA X:00 Y:69 P:A5 SP:FB CYC:2654
Only time 0x0200 is written before that, it gets 5A!
Suspect mem write: ADDR=1ff, VAL=5a, PC=cfc7, CYC=2523
That's not true - the code at $D009 writes the value #$AA to $0200 (and also writes #$AB to $0300, #$AC to #0303, and #$AD to $0400).

Code: Select all

D005  A9 AA     LDA #$AA                        A:5A X:81 Y:69 P:27 SP:FB PPU: 22,322 CYC:2608
D007  A2 00     LDX #$00                        A:AA X:81 Y:69 P:A5 SP:FB PPU: 22,328 CYC:2610
D009  81 80     STA ($80,X) @ 80 = 0200 = 5A    A:AA X:00 Y:69 P:27 SP:FB PPU: 22,334 CYC:2612
D00B  E8        INX                             A:AA X:00 Y:69 P:27 SP:FB PPU: 23, 11 CYC:2618
D00C  E8        INX                             A:AA X:01 Y:69 P:25 SP:FB PPU: 23, 17 CYC:2620
D00D  A9 AB     LDA #$AB                        A:AA X:02 Y:69 P:25 SP:FB PPU: 23, 23 CYC:2622
D00F  81 80     STA ($80,X) @ 82 = 0300 = 5B    A:AB X:02 Y:69 P:A5 SP:FB PPU: 23, 29 CYC:2624
D011  E8        INX                             A:AB X:02 Y:69 P:A5 SP:FB PPU: 23, 47 CYC:2630
D012  A9 AC     LDA #$AC                        A:AB X:03 Y:69 P:25 SP:FB PPU: 23, 53 CYC:2632
D014  81 80     STA ($80,X) @ 83 = 0303 = 5C    A:AC X:03 Y:69 P:A5 SP:FB PPU: 23, 59 CYC:2634
D016  A2 00     LDX #$00                        A:AC X:03 Y:69 P:A5 SP:FB PPU: 23, 77 CYC:2640
D018  A9 AD     LDA #$AD                        A:AC X:00 Y:69 P:27 SP:FB PPU: 23, 83 CYC:2642
D01A  81 FF     STA ($FF,X) @ FF = 0400 = 5D    A:AD X:00 Y:69 P:A5 SP:FB PPU: 23, 89 CYC:2644
D01C  AD 00 02  LDA $0200 = AA                  A:AD X:00 Y:69 P:A5 SP:FB PPU: 23,107 CYC:2650
D01F  C9 AA     CMP #$AA                        A:AA X:00 Y:69 P:A5 SP:FB PPU: 23,119 CYC:2654
On a side note, I should probably update the debug log format in my emulator (which was used to generate the nestest "reference log") to make that more clear - for example, "STA ($80,X) @ 82 = 0300 = 5B" means "($80,X) is equivalent to ($82), and ($82) points to $0300, and the value previously at $0300 was #$5B".
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

Concurser
Posts: 8
Joined: Fri Mar 06, 2020 12:30 pm

Re: Issue on Indirect,X addressing mode on nestest

Post by Concurser » Thu Aug 20, 2020 11:54 am

Thanks a lot, just discored that I had an unimplemented opcode: STA (ind,X) (81). Created a small trap to abort my emu execution when this happens.

Implied and Immediate opcodes are done here. I entered the phase on Nestest where there is a lot of RAM writes and usually it is hard to verify issues on a simple CPU register dump. Thanks for your tip.

Post Reply