It is currently Mon Dec 10, 2018 6:08 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 12 posts ] 
Author Message
PostPosted: Wed Apr 18, 2018 1:18 am 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 21
Location: Australia
Hi,

I am writing a NES emulator in Swift just for fun (yes I have read the sticky) and have implemented the CPU part and Mapper 0, no PPU or APU yet.
I want to test the instructions so I have loaded nestest.nes and set PC to 0xC000, it runs about 20 or so instructions before finding an opcode it doesn't know. This bit I can probably fix, but I thought it is probably better to first change all my logs to match those in the existing log file I found (this was hard to track down). I have started doing that and am having a dumb moment, I don't understand a part of the log file. What is the "= 74", "= 52", "= 73" mean after the STX instructions? Isn't this STX mean store what is found at memory location $00 in the X register? In my memory model there is nothing stored at location 0, and the subsequent log of the X register shows it is 0. Can anyone help me understand what is happening here?

Cheers,
Brett


Code:
C000  4C F5 C5  JMP $C5F5                       A:00 X:00 Y:00 P:24 SP:FD CPUC:0
      READ      $C000
      READ      $C001
      READ      $C002
C5F5  A2 00     LDX #$00                        A:00 X:00 Y:00 P:24 SP:FD CPUC:3
      READ      $C5F5
      READ      $C5F6
C5F7  86 00     STX $00 = 74                    A:00 X:00 Y:00 P:26 SP:FD CPUC:5
      READ      $C5F7
      READ      $C5F8
      WRITE     $0000
C5F9  86 10     STX $10 = 52                    A:00 X:00 Y:00 P:26 SP:FD CPUC:8
      READ      $C5F9
      READ      $C5FA
      WRITE     $0010
C5FB  86 11     STX $11 = 73                    A:00 X:00 Y:00 P:26 SP:FD CPUC:11
      READ      $C5FB
      READ      $C5FC
      WRITE     $0011


Top
 Profile  
 
PostPosted: Wed Apr 18, 2018 1:29 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3715
Location: Mountain View, CA
References: https://wiki.nesdev.com/w/index.php/Emulator_tests and http://www.qmtpro.com/~nes/misc/nestest.txt

The log you're posting should be compared to logs from Nintendulator. STX $00 = 74 is telling you that, at the time the instruction was encountered (but before it had run), the effective address (zero page address $00) contained value $74 (in hexadecimal; the $ is missing but implied).

Here are some more complicated examples which should then become self-explanatory assuming you understand the addressing modes in question, but I'll explain the first two:

Code:
CFDB  A1 80     LDA ($80,X) @ 80 = 0200 = 5A    A:5D X:00 Y:69 P:27 SP:FB CYC:118

DB65  91 33     STA ($33),Y = 0400 @ 0400 = 7F  A:87 X:06 Y:00 P:E5 SP:FB CYC:239

DB7B  6C 00 02  JMP ($0200) = DB7E              A:DB X:07 Y:00 P:E5 SP:FB CYC:326

E2F2  DD 00 06  CMP $0600,X @ 0678 = 81         A:80 X:78 Y:63 P:A5 SP:FB CYC:270

The entry at $CFDB is saying, in English, since indexed indirect addressing is used:

* @ 80 -- indicates the calculated effective address of ($80,X) was $80 (because X=$00, thus $80+X = $80)
* = 0200 -- indicates that the two bytes at $80 and $81 (for the indirect read) were $00 and $02 respectively, hence address $0200
* = 5A -- indicates that address $0200 contained $5A when the instruction was encountered

The entry at $DB65 is saying, in English, since indirect indexed addressing is used:

* = 0400 -- indicates that the two bytes at $33 and $34 (for the indirect read) were $00 and $04 respectively, hence the address $0400
* @ 0400 -- indicates the calculated effective address is $0400 (because Y=$00, thus $0400+Y = $0400).
* = 7F -- indicates that address $0400 contained $7F when the instruction was encountered

You get the idea. This general "real-time debugger" output is helpful for people doing reverse-engineering, since it gives them an idea of what the calculated effective address was (for relevant addressing modes), as well as what that memory location contained. Now you see why this is helpful in ensuring your 6502 CPU emulation is correct.


Top
 Profile  
 
PostPosted: Wed Apr 18, 2018 2:33 am 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 21
Location: Australia
Thanks for the very quick reply.

I have definitely read the nestext.txt file quite a few times, which is how I finally worked out how to run it without a PPU. And because I don't have the PPU I have to run it automated, and as a first pass I wanted to compare my log with the log I've seen people talk about, but I couldn't find it. I got the log I posted above from a post on this forum, it is called nestest-bus-cycles.log, I will hunt down one from Nintendulator and have a look at that one.

I am pretty sure I understand the Addressing Modes, and I do follow what you are saying, but I have only just recently learnt all this so I expect my understanding to be incorrect in places, hence the testing.

Looks like you have the same conclusion as me, there is a value $74 at location $00. Having loaded the rom myself and written the Memory mapper I know even without checking that I have nothing but a lot of 0's in the zero page. I have loaded the PRGROM at $C000 and mirrored it at $8000. But if you look at the log, the $74 is never written to the X register anyway.

So I have another question for you, what should be in the zero page after loading nestest.nes? I assume it is only what is written by the rom during execution, but here we are only 3 instructions in.

I really appreciate you taking the time to write the really comprehensive reply.

[EDIT]: I see the log file in the first link, I swear I have looked at that page a million times and never saw the link, that one looks much better. It has $00 instead of $74, which is exactly what I expected. Thanks for pointing out the obvious link to me (not being sarcastic), told you I was having a dumb moment.

Cheers,
Brett


Top
 Profile  
 
PostPosted: Wed Apr 18, 2018 6:45 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 3141
Location: Tampere, Finland
iOSBrett wrote:
Looks like you have the same conclusion as me, there is a value $74 at location $00. Having loaded the rom myself and written the Memory mapper I know even without checking that I have nothing but a lot of 0's in the zero page. I have loaded the PRGROM at $C000 and mirrored it at $8000. But if you look at the log, the $74 is never written to the X register anyway.

The log was taken with initial memory contents randomized. Anyway, it's not very useful to try to make your log match the disassembly in the log, simply make sure that the register values (A, X, Y, SP, PC) match. When you want to take it a step further you can also verify that the READ/WRITE cycles match.

There's a more terse log (without disassembly for ease of comparisons) at viewtopic.php?p=155910#p155910

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi


Top
 Profile  
 
PostPosted: Wed Apr 18, 2018 7:08 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20851
Location: NE Indiana, USA (NTSC)
iOSBrett wrote:
as a first pass I wanted to compare my log with the log I've seen people talk about

I agree with thefox: Just compare only program counter and AXYPS values, and you'll at least know where the program went off the rails. Unless nestest is reading uninitialized memory, the program counter and AXYPS values should not depend on initial contents of memory. My first guess is that you're trying to produce the identical disassembly in your emulator in order to be able to use the diff tool included with macOS.* It'd probably be easier to just write your own comparison tool that checks only PC or only PC+AXYPS.


* Assumption based on username and language choice. GNU/Linux and *BSD also include diff. Windows includes the similar fc, and Windows users can also get GNU diff through MSYS, Cygwin, or Windows 10 WSL.


Top
 Profile  
 
PostPosted: Wed Apr 18, 2018 12:54 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3715
Location: Mountain View, CA
Also make sure that CPUC (CPU cycles) also matches; there are many "edge cases" to cycle additions on the 65xxx series, such as during page wrapping operations. You can focus on this *after* you get opcodes/addressing modes emulated correctly. This is just one aspect of "timing-accurate" emulation.

As for ZP/RAM contents and so on on power-on (this is different than reset!), others have covered it already. It's also a commonly-discussed-hot-topic around here because there are some games which sort of "depend" on certain power-on values. I can link you to those threads if/when asked. In general, for starters, try initialising ZP/RAM to all zeros, see how the tests fair, then try initializing ZP/RAM to $FF and see how the tests fair. You get the idea.

As for CPU state itself, this is covered: https://wiki.nesdev.com/w/index.php/CPU_power_up_state
PPU has similar for when you get to it: https://wiki.nesdev.com/w/index.php/PPU_power_up_state


Top
 Profile  
 
PostPosted: Fri Apr 20, 2018 5:38 am 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 21
Location: Australia
thefox: Ahh that explains the weird values in 0 page.

And I have found it really helpful to compare the dissembled instructions. The 6502 page I used when implementing my emulated CPU had a couple of opcode errors in it, and I added more with my typos. I have had to change at least 5 opcode values that I would not have found with seeing the assembly code.

Debugging the CPU is strangely more fun than the code writing, can't say this is true in the day job though.


Top
 Profile  
 
PostPosted: Fri Apr 20, 2018 5:40 am 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 21
Location: Australia
tepples: Assumptions mostly correct.

I had planned on using sublime to do the diff, but it turns out it is not very good at that, so diff it is.
As posted above, using the diff has turned out to be really useful.


Top
 Profile  
 
PostPosted: Fri Apr 20, 2018 5:44 am 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 21
Location: Australia
koitsu: Yeah I am leaving the cycles to last, seems that none of my cycles match the log that you sent me. Even the first two instructions I have wrong in terms of number of cycles.

NesTest:

Code:
C000  4C F5 C5  JMP $C5F5                       A:00 X:00 Y:00 P:24 SP:FD CYC:  0
C5F5  A2 00     LDX #$00                        A:00 X:00 Y:00 P:24 SP:FD CYC:  9


Mine:

Code:
C000  4C F5 C5  JMP $C5F5                       A:00 X:00 Y:00 P:24 SP:FD CYC:0
C5F5  A2 00     LDX #$C5F6                      A:00 X:00 Y:00 P:24 SP:FD CYC:3


Thanks for those two links, I have implemented reset, but I didn't know that power on was different. I'll get everything else covered before taking that.

Thanks again to everyone for all the help, this forum is full of friendly and helpful people.

[EDIT]: Just noticed I am applying the wrong addressing mode in the LDX command, however the incorrect cycles are for the JMP command.


Top
 Profile  
 
PostPosted: Fri Apr 20, 2018 7:55 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20851
Location: NE Indiana, USA (NTSC)
CYC in a Nintendulator log is PPU dots, not CPU cycles. There are three dots in a cycle on NTSC systems and PAL famiclones, and it wraps around from 341 to 0. If you've ever emulated Z80 or LR35902 (Game Boy CPU) before, think of dots as like tstates and cycles as like mcycles.


Top
 Profile  
 
PostPosted: Fri Apr 20, 2018 11:18 am 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3715
Location: Mountain View, CA
tepples wrote:
CYC in a Nintendulator log is PPU dots, not CPU cycles. There are three dots in a cycle on NTSC systems and PAL famiclones, and it wraps around from 341 to 0. If you've ever emulated Z80 or LR35902 (Game Boy CPU) before, think of dots as like tstates and cycles as like mcycles.

Well that's a wonderfully misnamed field then. Good thing it's documented! :|


Top
 Profile  
 
PostPosted: Sat Apr 21, 2018 7:53 pm 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 21
Location: Australia
Oh! In that case my cycles may be correct.

:-)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group