nesdev.parodius.com Forum Index nesdev.parodius.com
NES Development and Strangulation Records message boards
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How do I switch from NROM to UNROM?

 
Post new topic   Reply to topic    nesdev.parodius.com Forum Index -> Newbie Help Center
View previous topic :: View next topic  
Author Message
SecretServiceDude



Joined: 22 Oct 2008
Posts: 99
Location: Los Angeles, CA

PostPosted: Sun Nov 09, 2008 2:42 am    Post subject: How do I switch from NROM to UNROM? Reply with quote

I've tried to set the mapper number to 2 in the iNES header, and I've toyed around with the ld65 linker config file, but I don't really know what I'm doing. Nestopia gives me a "Corrupt file!" message when I try to load the ROM.

Has anyone got an example handy that could help get me up and running?

If it helps at all, here are the current header and linker config I'm using for NROM:

Code:
.segment "HEADER"
   .byte "NES", 26, 2, 1       ; 32K PRG, 8K CHR


Code:
MEMORY {
   ZP:     start =   $10, size =   $F0, type = rw;
   HEADER: start =     0, size =    16, type = ro, fill = yes;
   ROMX:   start = $8000, size = $6000, type = ro, fill = yes;
   ROM0:   start = $E000, size = $1FF4, type = ro, fill = yes;
   ROMV:   start = $FFF4, size =    $C, type = ro, fill = yes;
   ROM2:   start =     0, size = $2000, type = ro, fill = yes;
   SRAM:   start = $0200, size = $0600, type = rw;
}

SEGMENTS {
   HEADER:   load = HEADER, type = ro;
   CODE:     load = ROM0,   type = ro, align = $100;
   CODE2:    load = ROM0,   type = ro, align = $100, optional=yes;
   RODATA:   load = ROM0,   type = ro;
   STRINGS:  load = ROM0,   type = ro, optional=yes;
   VECTORS:  load = ROMV,   type = ro;
   CHARS:    load = ROM2,   type = ro;
   BSS:      load = SRAM,   type = bss, align = $100;
   ZEROPAGE: load = ZP,     type = zp;
}


Also: Since UNROM uses CHR-RAM, where do I store the CHR data? Does it go into the RODATA segment? And is it necessary to copy 8 KB of CHR data to CHR-RAM before I can render anything?
Back to top
View user's profile Send private message
Bregalad



Joined: 12 Nov 2004
Posts: 4134
Location: Jongny, VD, Switzerland

PostPosted: Sun Nov 09, 2008 3:11 am    Post subject: Reply with quote

More or less. CHRRAM is that, just a RAM chip. When you power the console, it contains garbage (likely FFs). Usually, you'd want to store your CHR data in PRG ROM, and have a routine that copies it to RAM via $2006/$2007 updates. You don't have to updload it by 8kb chunks, but you can update any amount of tiles you want in any order, that's the big (and sole) advantage of CHRRAM, you're free to re-arrange tiles like you want, and even to change them by software.

I'm no CA64 expert, but you should probably remove the "ROM2" line in order to get it to work.

You should NOT set any CHRROM when doing this, let the byte in iNES header to $00. Only PRGROM data should be present.
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
tokumaru



Joined: 12 Feb 2005
Posts: 3581
Location: Rio de Janeiro - Brazil

PostPosted: Sun Nov 09, 2008 11:35 am    Post subject: Reply with quote

I believe that Nestopia requires UNROM games to have 128KB of ROM, and it's probably complaining about your 32KB.

Of course you don't have to use the whole 128KB if you don't want to, you could just use the last 32KB. But be sure to place your vectors and reset code in the last 16KB bank, because that's the one UNROM keeps mapped at $C000-$FFFF at all times. Before using the lower half ($8000-$BFFF), be sure to map the correct bank in there.

I'm sorry if I can't help you with assembler settings (my assembler of choice doesn't need any settings).

As Bregalad said, you must define 0 CHR-ROM pages in the header, and where you'll store the data is up to you. Since you're moving from NROM, what would make the most sense would be using one of the 6 new 16KB PRG-ROM banks you got for graphics, and have a simple routine to copy 8KB from it during start up, so it will pretty much feel like NROM for a while, until you decide to take more advantage of the extra ROM space and CHR-RAM freedom.
Back to top
View user's profile Send private message
Dwedit



Joined: 19 Nov 2004
Posts: 1490

PostPosted: Sun Nov 09, 2008 12:16 pm    Post subject: Reply with quote

I've seen 64k sized games which work as Mapper #2 (Bee 52). I'd think it was just complaining that the size in the header does not match the filesize.
Back to top
View user's profile Send private message Visit poster's website
tokumaru



Joined: 12 Feb 2005
Posts: 3581
Location: Rio de Janeiro - Brazil

PostPosted: Sun Nov 09, 2008 1:23 pm    Post subject: Reply with quote

Dwedit wrote:
I've seen 64k sized games which work as Mapper #2 (Bee 52).

I believe this is the case with Zanac as well. The ROM I've checked contains all zeroes in the first 64KB.

Quote:
I'd think it was just complaining that the size in the header does not match the filesize.

Nestopia seems to only accept mapper 2 games that are 128KB or 256KB, everything else is "corrupted".
Back to top
View user's profile Send private message
SecretServiceDude



Joined: 22 Oct 2008
Posts: 99
Location: Los Angeles, CA

PostPosted: Sun Nov 09, 2008 7:04 pm    Post subject: Reply with quote

Okay, I've updated the header and linker config file. Nestopia no longer displays the "Corrupt file!" message; however, now all I've got is a blank screen.

My CHR data is located in the BANK2 segment. I suspect one of my problems is that I'm not successfully copying the data to CHR-RAM. This is my first attempt at bank switching, so I don't really know how to do it. If improper bank switching is the culprit, how do I set it up properly?

Below are my current header and linker config for UNROM:

Code:
.segment "HEADER"
   .byte "NES", $1A            ; "NES" followed by MS-DOS end-of-file
   .byte $08                   ; Size of PRG ROM in 16 KB units (128 KB for UNROM)
   .byte $00                   ; Size of CHR ROM in 8 KB units (Value 0 means the board uses CHR RAM)
   .byte $20, $00              ; Mapper 2 = UNROM/UOROM
   .byte $00                   ; Size of PRG RAM in 8 KB units (Value 0 infers 8 KB for compatibility)


Code:
MEMORY {
   ZP:     start =   $00, size =  $100, type = rw;
   HEADER: start =   $00, size =   $10, type = ro, fill = yes;
   RAM:    start =  $200, size =  $600, type = rw;
   PRG:    start = $8000, size = $8000, type = ro, file = %O;
   PRG2:   start = $C000, size = $4000, type = ro, file = %O;
   PRG3:   start = $C000, size = $4000, type = ro, file = %O;
   PRG4:   start = $C000, size = $4000, type = ro, file = %O;
   PRG5:   start = $C000, size = $4000, type = ro, file = %O;
   PRG6:   start = $C000, size = $4000, type = ro, file = %O;
   PRG7:   start = $C000, size = $4000, type = ro, file = %O;
   PRG8:   start = $C000, size = $4000, type = ro, file = %O;
}
SEGMENTS {
   HEADER:     load = HEADER, type = ro;
   CODE:       load = PRG,  type = ro, start = $8000;
   RODATA:     load = PRG,  type = ro;
   DATA:       load = RAM,  type = bss;
   ZEROPAGE:   load = ZP,   type = zp;
   BSS:        load = RAM,  type = bss, define = yes, align = $100;
   VECTORS:    load = PRG,  type = ro, start = $FFF4;
   BANK2:      load = PRG2, type = ro, start = $C000;
   VECTORS2:   load = PRG2, type = ro, start = $FFF4;
   BANK3:      load = PRG3, type = ro, start = $C000;
   VECTORS3:   load = PRG3, type = ro, start = $FFF4;
   BANK4:      load = PRG4, type = ro, start = $C000;
   VECTORS4:   load = PRG4, type = ro, start = $FFF4;
   BANK5:      load = PRG5, type = ro, start = $C000;
   VECTORS5:   load = PRG5, type = ro, start = $FFF4;
   BANK6:      load = PRG6, type = ro, start = $C000;
   VECTORS6:   load = PRG6, type = ro, start = $FFF4;
   BANK7:      load = PRG7, type = ro, start = $C000;
   VECTORS7:   load = PRG7, type = ro, start = $FFF4;
   BANK8:      load = PRG8, type = ro, start = $C000;
   VECTORS8:   load = PRG8, type = ro, start = $FFF4;
}
Back to top
View user's profile Send private message
SecretServiceDude



Joined: 22 Oct 2008
Posts: 99
Location: Los Angeles, CA

PostPosted: Sun Nov 09, 2008 11:17 pm    Post subject: Reply with quote

tokumaru wrote:
Of course you don't have to use the whole 128KB if you don't want to, you could just use the last 32KB. But be sure to place your vectors and reset code in the last 16KB bank, because that's the one UNROM keeps mapped at $C000-$FFFF at all times.

For the life of me, I can't figure out how to do that. Strangely, when I was working with NROM, I had no problem placing the vectors and reset code in the last 16KB bank; but with my UNROM project, the program simply refuses to display anything unless the reset code is located precisely at $8000. If I try to relocate the code to $C000, all I get is a black screen.

This is driving me crazy. What's a man to do?
Back to top
View user's profile Send private message
SecretServiceDude



Joined: 22 Oct 2008
Posts: 99
Location: Los Angeles, CA

PostPosted: Mon Nov 10, 2008 1:53 am    Post subject: Reply with quote

YESSSS!!!

After much struggling and frustration, I finally built a working UNROM project! I can now write to CHR-RAM, which I intend to exploit shamelessly for maximum kicking of ass.

Thank you all for your suggestions; I'd have been completely lost without them.

The sky's the limit. I'm stoked. Smile
Back to top
View user's profile Send private message
clueless



Joined: 07 Sep 2008
Posts: 85
Location: Wisconsin, USA

PostPosted: Mon Nov 10, 2008 9:44 am    Post subject: Reply with quote

I'm just curious... what was the problem? What did you change to make it work?
Back to top
View user's profile Send private message
SecretServiceDude



Joined: 22 Oct 2008
Posts: 99
Location: Los Angeles, CA

PostPosted: Mon Nov 10, 2008 6:40 pm    Post subject: Reply with quote

clueless wrote:
I'm just curious... what was the problem? What did you change to make it work?

I wasn't aware that I had to place the fixed bank after the other PRG ROM banks in the NES file. I had previously been writing the fixed bank immediately following the iNES header.

Of course, tokumaru told me exactly what to do from the beginning:

tokumaru wrote:
But be sure to place your vectors and reset code in the last 16KB bank, because that's the one UNROM keeps mapped at $C000-$FFFF at all times.

I guess I was just being dense. Confused


Anyhow, below are the header, linker config, and batch file I use to build my (now working!) UNROM project:


Header:
Code:
.segment "HEADER"
   ; Header for UNROM board
   .byte "NES", $1A            ; "NES" followed by MS-DOS end-of-file
   .byte $08                   ; Size of PRG ROM in 16 KB units (128 KB for UNROM)
   .byte $00                   ; Size of CHR ROM in 8 KB units (Value 0 means the board uses CHR RAM)
   .byte $20, $00              ; Mapper 2 = UNROM/UOROM
   .byte $00                   ; Size of PRG RAM in 8 KB units (Value 0 infers 8 KB for compatibility)


Linker config:
Code:
MEMORY {
   M_ZEROPAGE:     start =   $00, size =  $100, type = rw;
   M_RAM:          start =  $200, size =  $600, type = rw;
   M_HEADER:       start =    $0, size =   $10, type = ro, fill = yes, file = "build\ld65\header.bin";
   M_WORKRAM:      start = $6000, size = $2000, type = rw;

   # PRG ROM banks (16 KB each, bank 7 is fixed)
   M_PRGBANK0:     start = $8000, size = $4000, type = ro, fill = yes, file = "build\ld65\bank0.prg";
   M_PRGBANK1:     start = $8000, size = $4000, type = ro, fill = yes, file = "build\ld65\bank1.prg";
   M_PRGBANK2:     start = $8000, size = $4000, type = ro, fill = yes, file = "build\ld65\bank2.prg";
   M_PRGBANK3:     start = $8000, size = $4000, type = ro, fill = yes, file = "build\ld65\bank3.prg";
   M_PRGBANK4:     start = $8000, size = $4000, type = ro, fill = yes, file = "build\ld65\bank4.prg";
   M_PRGBANK5:     start = $8000, size = $4000, type = ro, fill = yes, file = "build\ld65\bank5.prg";
   M_PRGBANK6:     start = $8000, size = $4000, type = ro, fill = yes, file = "build\ld65\bank6.prg";
   M_PRGFIXED:     start = $C000, size = $4000, type = ro, fill = yes, file = "build\ld65\fixed.prg";
}

SEGMENTS {
   HEADER:         load = M_HEADER,   type = ro;
   CODE:           load = M_PRGFIXED, type = ro, start = $C000;
   RODATA:         load = M_PRGFIXED, type = ro;
   VECTORS:        load = M_PRGFIXED, type = ro, start = $FFF0;
   ZEROPAGE:       load = M_ZEROPAGE, type = zp;
   BSS:            load = M_RAM,      type = bss, align = $100;
   PRGBANK0:       load = M_PRGBANK0, type = ro, start = $8000;
   PRGBANK1:       load = M_PRGBANK1, type = ro, start = $8000;
   PRGBANK2:       load = M_PRGBANK2, type = ro, start = $8000;
   PRGBANK3:       load = M_PRGBANK3, type = ro, start = $8000;
   PRGBANK4:       load = M_PRGBANK4, type = ro, start = $8000;
   PRGBANK5:       load = M_PRGBANK5, type = ro, start = $8000;
   PRGBANK6:       load = M_PRGBANK6, type = ro, start = $8000;
}


Batch file:
Code:
@ECHO OFF
SET NESFILE="Bionic Commander (U).nes"
SET BUILD1=build\ca65
SET BUILD2=build\ld65

REM Assemble
call ca65 -I source source\main.s -o %BUILD1%\main.o
call ca65 -I source source\input.s -o %BUILD1%\input.o
call ca65 -I source source\level1.s -o %BUILD1%\level1.o
call ca65 -I source source\util.s -o %BUILD1%\util.o

REM Link
call ld65 --obj-path %BUILD1% -C unrom.cfg main.o input.o level1.o util.o -o ""

REM Create NES file
call copy /b /y %BUILD2%\header.bin %NESFILE%
call copy /b /y %NESFILE% + %BUILD2%\bank0.prg %NESFILE%
call copy /b /y %NESFILE% + %BUILD2%\bank1.prg %NESFILE%
call copy /b /y %NESFILE% + %BUILD2%\bank2.prg %NESFILE%
call copy /b /y %NESFILE% + %BUILD2%\bank3.prg %NESFILE%
call copy /b /y %NESFILE% + %BUILD2%\bank4.prg %NESFILE%
call copy /b /y %NESFILE% + %BUILD2%\bank5.prg %NESFILE%
call copy /b /y %NESFILE% + %BUILD2%\bank6.prg %NESFILE%
call copy /b /y %NESFILE% + %BUILD2%\fixed.prg %NESFILE%
pause
Back to top
View user's profile Send private message
clueless



Joined: 07 Sep 2008
Posts: 85
Location: Wisconsin, USA

PostPosted: Mon Nov 10, 2008 7:47 pm    Post subject: Reply with quote

It is great that you've got it to work. Please don't take the following as any sort of detraction of your skill.

You don't have to use a batch file. The ld65 linker is fully capable of creating a properly laid out .nes file in iNes format.

At the moment my project uses MMC1 (16K banks) with 4 banks. Three (ROM0, ROM1, TILES) are at $8000 and the non-swappable (ROMK and ROMV) at $c000.

It appears to me that the order the segments are listed in the "SEGMENTS" block does not matter. What appears to matter is the order of the sections "MEMORY" that have the attribute "file = %O". They are written to the output file in that order.

[1] https://www.ecoligames.com/trac/nes-game/nes-game/browser/trunk/src/linker.cfg
Back to top
View user's profile Send private message
SecretServiceDude



Joined: 22 Oct 2008
Posts: 99
Location: Los Angeles, CA

PostPosted: Mon Nov 10, 2008 8:11 pm    Post subject: Reply with quote

Everything you said is absolutely correct. In fact, until recently I was using the "file = %O" attribute to have the linker generate the NES file directly. It's true that the order of the segments doesn't matter, only the memory sections.

But still, as a matter of personal preference, I like having the banks separated into distinct files. That way, I can easily throw a bank into a hex editor and immediately see its contents. Also, I imagine that having separate files might make it easier to transfer the game to an actual cartridge later on.

I'm still pretty new at this stuff, so the project will undoubtedly evolve for a while before everything coalesces. At this point, I'm just happy to have something that works, because wrestling with that linker config was a real pain. Razz

EDIT: If anyone else out there is struggling to understand how ld65 config files work, this site is pretty useful.
Back to top
View user's profile Send private message
clueless



Joined: 07 Sep 2008
Posts: 85
Location: Wisconsin, USA

PostPosted: Mon Nov 10, 2008 8:16 pm    Post subject: Reply with quote

(going off topic)

Smile Linkers are indeed a dark art. Second only to the dreaded "scsi chain".

http://74.125.45.104/search?q=cache:plYiNfv4MCwJ:https://0x55517066.adsl.cybercity.dk/quotes/+quote+goat+scsi+chain&hl=en&ct=clnk&cd=2&gl=us&client=firefox-a

Search for "John Woods".

Than read the quote immediately above that one and immediately below it.
Back to top
View user's profile Send private message
clueless



Joined: 07 Sep 2008
Posts: 85
Location: Wisconsin, USA

PostPosted: Mon Nov 10, 2008 8:57 pm    Post subject: Reply with quote

SecretServiceDude,

Interesting idea about keeping ROM segments separate to make them easier to "explore" using a hex-editor. You inspired me to hack my build scripts. Smile

I now have two linker files and two build targets: The full NES game and just the tiles as if it were a CHRROM game with 16K of tiles.
Back to top
View user's profile Send private message
SecretServiceDude



Joined: 22 Oct 2008
Posts: 99
Location: Los Angeles, CA

PostPosted: Mon Nov 10, 2008 9:22 pm    Post subject: Reply with quote

Glad to be of service. After all, it's in my name!

I really love this place because of all the great ideas everyone presents. If these forums didn't exist, I may have given up on my project already, because there are so many things I never could have figured out without all the helpful information/suggestions found here.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    nesdev.parodius.com Forum Index -> Newbie Help Center All times are GMT - 7 Hours
Page 1 of 1

 
Jump to:  
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 vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group