It is currently Mon Nov 20, 2017 12:57 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 31 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: Sun Oct 15, 2017 11:08 am 
Offline
User avatar

Joined: Mon Nov 26, 2012 6:12 am
Posts: 22
So far I've only been using the default mapper, but I want to try using MMC3. I read the relevant wiki articles but I can't get anything to work. It will compile, but the resulting rom just produces a blank screen in the emulator. The identical code works just fine with the default mapper. It's not doing anything fancy, just writing some colors to the palette to make sure it works.

So I guess what I'm looking for is a sort of "quick setup template" for getting something (anything) running using MMC3. For example:

  • What do I put in the header?
  • Where should my code start?
  • Is there something special I need to do at the start of the reset code to get things set up? If so, does that need to happen before or after the usual initialization code (waiting to power up etc)?

Thanks!


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 11:21 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6446
Location: UK (temporarily)
Have you tried using a debugging emulator (FCEUX on Windows, Nintendulator, Mesen)? It should help you narrow down what's going wrong.

Guessing, the most likely reason something doesn't work when MMC3 is that your reset function isn't in the very last 8 KiB of PRG; the specific banks mapped to $8000-$DFFF aren't guaranteed on power-up.


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 11:25 am 
Offline
User avatar

Joined: Mon Nov 26, 2012 6:12 am
Posts: 22
lidnariq wrote:
Have you tried using a debugging emulator (FCEUX on Windows, Nintendulator, Mesen)? It should help you narrow down what's going wrong.

Guessing, the most likely reason something doesn't work when MMC3 is that your reset function isn't in the very last 8 KiB of PRG; the specific banks mapped to $8000-$DFFF aren't guaranteed on power-up.


I'm using FCEUX, though I'm not sure where to look to find out what's going wrong; all I can tell from that is that there is something going wrong since it's not setting the palettes.

I put the code at $C000.


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 11:31 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6446
Location: UK (temporarily)
Yeah, move the code to $E000 instead. Or, insert a stub that writes 0 to $8000 (so that $C000 is the fixed bank)


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 11:34 am 
Offline
User avatar

Joined: Mon Nov 26, 2012 6:12 am
Posts: 22
lidnariq wrote:
Yeah, move the code to $E000 instead. Or, insert a stub that writes 0 to $8000 (so that $C000 is the fixed bank)


Moving the code to $E000 had no effect. :(


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 11:37 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6446
Location: UK (temporarily)
How big is your PRG? What happens when you open the FCEUX debugger, reset, and take the first couple steps? Does it do what you think it should?

What assembler are you using? When you say you moved the code from $C000 to $E000, did it actually move where it was in the file?


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 11:55 am 
Offline
User avatar

Joined: Mon Nov 26, 2012 6:12 am
Posts: 22
lidnariq wrote:
How big is your PRG? What happens when you open the FCEUX debugger, reset, and take the first couple steps? Does it do what you think it should?

What assembler are you using? When you say you moved the code from $C000 to $E000, did it actually move where it was in the file?


Here's my header:
Code:
   .db "NES", $1a ;identification of the iNES header
   .db $04 ;number of 16KB PRG-ROM pages
   .db $08 ;number of 8KB CHR-ROM pages
   .db $40 ;MMC3
   .dsb 9, $00 ;clear the remaining bytes


When I opened the debugger and reset, the first instruction was 0101 then it was a bunch of 00s followed by a bunch of FFs followed by a bunch of 00s again in a repeating pattern like that. Seems very incorrect...

The assembler I'm using is ASM6. It's served me perfectly well with the default mapper.

Upon opening the file in a hex editor, it appears to be only $2000 in size to begin with, and everything after about $00A8 or so is just completely filled with 00s.


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 12:16 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6446
Location: UK (temporarily)
For that header, the file you load should be exactly 16+4*16384+8*8192=131088 bytes. Since your file is only 8 KiB, it seems safe to assume that FCEUX is loading garbage for the remainder of the file. Maybe try starting off with just your known-working NROM bit and just change the mapper number to 4 so that you can reduce the number of variables.

Since you now specify 64 KiB of PRG, you need to put the reset handler starting at 56 KiB into the file. I'm not sufficiently versed in ASM6 to know how to do that...


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 12:26 pm 
Offline
User avatar

Joined: Mon Nov 26, 2012 6:12 am
Posts: 22
lidnariq wrote:
For that header, the file you load should be exactly 16+4*16384+8*8192=131088 bytes. Since your file is only 8 KiB, it seems safe to assume that FCEUX is loading garbage for the remainder of the file. Maybe try starting off with just your known-working NROM bit and just change the mapper number to 4 so that you can reduce the number of variables.

Since you now specify 64 KiB of PRG, you need to put the reset handler starting at 56 KiB into the file. I'm not sufficiently versed in ASM6 to know how to do that...


Taking a program that was working as an NROM and changing it to MMC3 and nothing else... works!
Changing the existing MMC3 program to have only 1 PRG page... works!

Thanks!

Although interestingly, even the working NROM rom is only $6000 in size and appears to have no vectors at the end indicating NMI, IRQ, and reset, which makes me wonder how that's even capable of working. The code seems to start right after the header.


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 12:35 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1823
Location: DIGDUG
$6010 bytes is a valid size for "NROM 128" boards. $10 header+$4000 PRG + $2000 CHR.

If there is only 1 bank of PRG ROM, it is loaded to $8000-bfff and mirrored at $c000-ffff.

I would expect it to work.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Sun Oct 15, 2017 2:00 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1823
Location: DIGDUG
To answer your original question.

If you are using asm6, you need to fill banks (if there isn't code yet) with zeros using

pad and base statements.

And to initialize the MMC3, you should explicitly set every PRG and CHR bank and set the PPU mirroring.

Your init code should be in the last $2000 bytes of your PRG ROM, which will map as the fixed bank at $e000-ffff. Your vectors will also be in this bank.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Tue Oct 17, 2017 2:22 am 
Offline
User avatar

Joined: Mon Nov 26, 2012 6:12 am
Posts: 22
dougeff wrote:
To answer your original question.

If you are using asm6, you need to fill banks (if there isn't code yet) with zeros using

pad and base statements.

And to initialize the MMC3, you should explicitly set every PRG and CHR bank and set the PPU mirroring.

Your init code should be in the last $2000 bytes of your PRG ROM, which will map as the fixed bank at $e000-ffff. Your vectors will also be in this bank.


Thanks! Although I don't really understand how to use those .base or .pad statements. When I did this:

Code:
   .base $6000

   .base $8000

   .base $A000

   .base $C000

   .base $E000


The rom was $4000 in size with the reset vectors at $200A-$200F. When loaded in an emulator, it doesn't function. When I did this:

Code:
   .base $6000
   .pad $2000

   .base $8000
   .pad $2000

   .base $A000
   .pad $2000

   .base $C000
   .pad $2000

   .base $E000


The compiler said "Value out of range" at all the lines corresponding to the .pad statements. It wouldn't produce a rom at all.
Through trial and error, the only thing I could get to produce a functioning rom was this:

Code:
   .base $8000


Which is fine until the time comes when I'll need more memory.


Top
 Profile  
 
PostPosted: Tue Oct 17, 2017 7:29 am 
Offline
User avatar

Joined: Wed Sep 07, 2005 9:55 am
Posts: 304
Location: Phoenix, AZ
For ram I use enums:

Code:
.enum $6000
SomeVar:    .db 0
SomeWord:   .dw 0
SomeArray:  .dsb SIZE_OF_ARRAY
.ende


For an 8k bank:

Code:
   .base $8000
   ; code/data
IF $ > $9FFF
ERROR "Bank overflow"
ENDIF
  .org $A000


Repeat for however many banks you have, changing the addresses as needed.


Top
 Profile  
 
PostPosted: Tue Oct 17, 2017 8:55 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 1823
Location: DIGDUG
So, let's talk about what the assembler is trying to do.

As it goes line by line, it's counting bytes. This is so, when it sees a label, it knows what address it will have, in case it needs to use it in your code.

(Default starting address = 0)

Lda #0 (it counts 2 bytes)
Label: (this label now has the value 0002)
Sta 0 (it counts 2 bytes)
Label2: (this label has the value 0004)
Jmp Label (this will translate to jump to 0002)

Since it's a 6502, there is a max of ffff for the count, if it rolls over that, error.

You can change the assembler's count with base statements.

Base $8000

Lda #0 (it counts 2 bytes)
Label: (this label now has the value 8002)
Sta 0 (it counts 2 bytes)
Label2: (this label has the value 8004)
Jmp Label (this will translate to jump to 8002)

You can use 'org' or 'pad' statements, to tell the assembler to start counting UP to a certain address. It has to be larger than (or equal to) the current count.

Base $8000

Some code here

Pad $a000
(Will fill with zero from the end of the code till reaches $a000)

Base $8000
(Resets the count back to $8000)
Pad $a000
(Fills $2000 bytes of zeros)

Etc.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Tue Oct 17, 2017 3:52 pm 
Offline
User avatar

Joined: Mon Nov 26, 2012 6:12 am
Posts: 22
I get it now. That's working.

Thanks so much for your help! That was not at all clear from the ASM6 documentation.

I've poked around with NES programming a tiny bit many years ago but this is the first time I've sat down to actually attempt to make a full game from start to finish; we'll see how far I get.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 31 posts ]  Go to page 1, 2, 3  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google Adsense [Bot], Yahoo [Bot] and 11 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