 |
nesdev.parodius.com NES Development and Strangulation Records message boards
|
| View previous topic :: View next topic |
| Author |
Message |
SecretServiceDude

Joined: 22 Oct 2008 Posts: 99 Location: Los Angeles, CA
|
Posted: Sun Nov 09, 2008 2:42 am Post subject: How do I switch from NROM to UNROM? |
|
|
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 |
|
 |
Bregalad

Joined: 12 Nov 2004 Posts: 4134 Location: Jongny, VD, Switzerland
|
Posted: Sun Nov 09, 2008 3:11 am Post subject: |
|
|
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 |
|
 |
tokumaru

Joined: 12 Feb 2005 Posts: 3581 Location: Rio de Janeiro - Brazil
|
Posted: Sun Nov 09, 2008 11:35 am Post subject: |
|
|
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 |
|
 |
Dwedit

Joined: 19 Nov 2004 Posts: 1490
|
Posted: Sun Nov 09, 2008 12:16 pm Post subject: |
|
|
| 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 |
|
 |
tokumaru

Joined: 12 Feb 2005 Posts: 3581 Location: Rio de Janeiro - Brazil
|
Posted: Sun Nov 09, 2008 1:23 pm Post subject: |
|
|
| 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 |
|
 |
SecretServiceDude

Joined: 22 Oct 2008 Posts: 99 Location: Los Angeles, CA
|
Posted: Sun Nov 09, 2008 7:04 pm Post subject: |
|
|
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 |
|
 |
SecretServiceDude

Joined: 22 Oct 2008 Posts: 99 Location: Los Angeles, CA
|
Posted: Sun Nov 09, 2008 11:17 pm Post subject: |
|
|
| 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 |
|
 |
SecretServiceDude

Joined: 22 Oct 2008 Posts: 99 Location: Los Angeles, CA
|
Posted: Mon Nov 10, 2008 1:53 am Post subject: |
|
|
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.  |
|
| Back to top |
|
 |
clueless
Joined: 07 Sep 2008 Posts: 85 Location: Wisconsin, USA
|
Posted: Mon Nov 10, 2008 9:44 am Post subject: |
|
|
| I'm just curious... what was the problem? What did you change to make it work? |
|
| Back to top |
|
 |
SecretServiceDude

Joined: 22 Oct 2008 Posts: 99 Location: Los Angeles, CA
|
Posted: Mon Nov 10, 2008 6:40 pm Post subject: |
|
|
| 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.
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 |
|
 |
clueless
Joined: 07 Sep 2008 Posts: 85 Location: Wisconsin, USA
|
Posted: Mon Nov 10, 2008 7:47 pm Post subject: |
|
|
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 |
|
 |
SecretServiceDude

Joined: 22 Oct 2008 Posts: 99 Location: Los Angeles, CA
|
Posted: Mon Nov 10, 2008 8:11 pm Post subject: |
|
|
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.
EDIT: If anyone else out there is struggling to understand how ld65 config files work, this site is pretty useful. |
|
| Back to top |
|
 |
clueless
Joined: 07 Sep 2008 Posts: 85 Location: Wisconsin, USA
|
|
| Back to top |
|
 |
clueless
Joined: 07 Sep 2008 Posts: 85 Location: Wisconsin, USA
|
Posted: Mon Nov 10, 2008 8:57 pm Post subject: |
|
|
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.
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 |
|
 |
SecretServiceDude

Joined: 22 Oct 2008 Posts: 99 Location: Los Angeles, CA
|
Posted: Mon Nov 10, 2008 9:22 pm Post subject: |
|
|
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 |
|
 |
|
|
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
|