NESASM & AOROM Programming - a few questions
Moderator: Moderators
NESASM & AOROM Programming - a few questions
I did not find satisfactory information in this topic on the forum - maybe the mapper is not very popular in terms of programming.
1. AOROM switches banks size 32KB - so every bank must be a copy of the RESET code and at the end of each bank Vectors code. Right? Generally, I would like to know how to best prepare this mapper so that I have no problem with 'Label multiply defined' errors (after all, a lot of code will be the same in every bank).
2. In AOROM, you can control Nametable mirroring directly in code, but I have not found anywhere exactly how (bit 4 controls it, but how do you do it correctly?)
3. What are the advantages of AOROM versus UxROM? Seems to be more onerous because of the size of the bank switched, but some advantages in that it must be (mirroring control probably is an advantage).
4. I have a Mashou cartridge (BNROM) - Will converting it to AOROM will be limited to changing the CIRAM A10 (nametable mirroring) connection. On the wiki I read "BNROM is the same as AMROM except it uses a fixed horizontal or vertical mirroring".
5. By converting the BNROM to 512KB (as in the link below) and changing the CIRAM A10 (nametable mirroring) connection it will be exactly AOROM-512.? (Compatible with commercial AOROM (256KB)
https://forums.nesdev.com/viewtopic.php ... 0&p=168339
1. AOROM switches banks size 32KB - so every bank must be a copy of the RESET code and at the end of each bank Vectors code. Right? Generally, I would like to know how to best prepare this mapper so that I have no problem with 'Label multiply defined' errors (after all, a lot of code will be the same in every bank).
2. In AOROM, you can control Nametable mirroring directly in code, but I have not found anywhere exactly how (bit 4 controls it, but how do you do it correctly?)
3. What are the advantages of AOROM versus UxROM? Seems to be more onerous because of the size of the bank switched, but some advantages in that it must be (mirroring control probably is an advantage).
4. I have a Mashou cartridge (BNROM) - Will converting it to AOROM will be limited to changing the CIRAM A10 (nametable mirroring) connection. On the wiki I read "BNROM is the same as AMROM except it uses a fixed horizontal or vertical mirroring".
5. By converting the BNROM to 512KB (as in the link below) and changing the CIRAM A10 (nametable mirroring) connection it will be exactly AOROM-512.? (Compatible with commercial AOROM (256KB)
https://forums.nesdev.com/viewtopic.php ... 0&p=168339
Re: NESASM & AOROM Programming - a few questions
Yes, Reset, NMI and IRQ handlers must be present in every bank, even if they're stubs that simply select the bank where the actual handlers are and jumps to them (if you do switch banks in the NMI or IRQ handlers, you should save the current bank's number on the stack so you can restore it before returning).sdm wrote:1. AOROM switches banks size 32KB - so every bank must be a copy of the RESET code and at the end of each bank Vectors code. Right?
One good way to deal with repeated code is to write it in a separate file and INCLUDE it in the main file as many times as necessary, so that any changes to this code are done in a single place, and automatically reflected in all instances where it's used.Generally, I would like to know how to best prepare this mapper so that I have no problem with 'Label multiply defined' errors (after all, a lot of code will be the same in every bank).
As for repeating labels, I've had to deal with this problem in other assemblers: in ASM6 I did Label = * instead of Label: as the former can be done multiple times without errors. In ca65 I use scopes and "copy" the necessary labels to the global scope if they aren't already defined. I'm not sure how to do it in NESASM because I never worked with it, but my first try would be to wrap any repeat label in a block like this:
Code: Select all
IFNDEF Label
Label:
ENDIF
AxROM boards use single-screen mirroring, meaning that at any given time, only 1 name table is visible, mirrored in the 4 NT slots the PPU has. The value you write to bit 4 selects which name table this is.2. In AOROM, you can control Nametable mirroring directly in code, but I have not found anywhere exactly how (bit 4 controls it, but how do you do it correctly?)
I don't like 1-screen mirroring because you can't do 100% clean horizontal scroll with it unless you do something extreme like hiding the rightmost 8 pixels of the screen using an obscene amount of sprites, so for me the advantage is precisely the 32KB bank size.3. What are the advantages of AOROM versus UxROM? Seems to be more onerous because of the size of the bank switched, but some advantages in that it must be (mirroring control probably is an advantage).
Different projects have different requirements, so in some cases you may need access to larger chunks of switchable data, but in other cases, having a fixed 16KB bank might make things easier if 16KB a good part of it is usable through the entire game (e.g. the core engine fits in 16KB). There's no obviously "superior" mapper in this case.
I personally like (oversize) BNROM better, because I find vertical or horizontal mirroring more useful than single-screen, even if it's fixed. Not having to use 1 of the bits for mirroring means you get twice the banks (16 x 32KB = 512KB) too.4. I have a Mashou cartridge (BNROM) - Will converting it to AOROM will be limited to changing the CIRAM A10 (nametable mirroring) connection. On the wiki I read "BNROM is the same as AMROM except it uses a fixed horizontal or vertical mirroring".
To implement the selectable mirroring you'd have to steal one of the banking bits, so no, you can't make an AOROM-512 using a 4-bit register ('161 chip). You'd either need a second '161 or replace it with a larger register, which means different instructions.5. By converting the BNROM to 512KB (as in the link below) and changing the CIRAM A10 (nametable mirroring) connection it will be exactly AOROM-512.? (Compatible with commercial AOROM (256KB)
viewtopic.php?t=14080&p=168339
Re: NESASM & AOROM Programming - a few questions
I would definitely move away from NESASM for a project of this size. Believe me, the 5 minutes spent learning a slightly different syntax is worth it.
nesdoug.com -- blog/tutorial on programming for the NES
Re: NESASM & AOROM Programming - a few questions
I triedtokumaru wrote: One good way to deal with repeated code is to write it in a separate file and INCLUDE it in the main file as many times as necessary, so that any changes to this code are done in a single place, and automatically reflected in all instances where it's used.
.include "reset_code.asm"
In every bank and unfortunately pops up '' Label multiply defined" : /
It probably also will not work with NESASM3.As for repeating labels, I've had to deal with this problem in other assemblers: in ASM6 I did Label = * instead of Label: as the former can be done multiple times without errors. In ca65 I use scopes and "copy" the necessary labels to the global scope if they aren't already defined. I'm not sure how to do it in NESASM because I never worked with it, but my first try would be to wrap any repeat label in a block like this:
As for nametable mirroring:
I just noticed that UxROM only has Single-screen mirroring. ;/ So the first and second NameTable in 2KB VRAM are exactly the same? I do not quite understand the meaning of this use. Is the change mirroring V / H in the code has some use?
I will probably be forced to do this some time later..dougeff wrote:I would definitely move away from NESASM for a project of this size. Believe me, the 5 minutes spent learning a slightly different syntax is worth it.
Re: NESASM & AOROM Programming - a few questions
Yeah, if you don't do anything about the labels, that's expected.sdm wrote:I tried
.include "reset_code.asm"
In every bank and unfortunately pops up '' Label multiply defined" : /
Did you try IFNDEF? NESASM's documentation says it has this directive. This block will only be processed if the label isn't defined yet, so it'll only be defined the first time the code is included. You should put the Reset, IRQ and NMI labels inside IFNDEF blocks like I said before, while internal labels can be temporary. To make sure that there's a global label separating the multiple instances of the included file you can just put a unique label before each include:It probably also will not work with NESASM3.
Code: Select all
EndOfBank0:
.include "reset_nmi_irq_and_vectors.asm"
(...)
EndOfBank1:
.include "reset_nmi_irq_and_vectors.asm"
(...)
Nope, U*ROM uses fixed vertical or horizontal mirroring.I just noticed that UxROM only has Single-screen mirroring.
NT mirroring exists because the PPU has a virtual space of 2x2 name tables (512x480 pixels) it can scroll around, but the RAM chip installed inside the NES can only hold 2 name tables, meaning that some of the data has to be repeated.So the first and second NameTable in 2KB VRAM are exactly the same? I do not quite understand the meaning of this use.
Nintendo them decided to route to the cartridge the signals necessary to manipulate the mirroring layout, instead of hardcoding it to some arbitrary configuration inside the console, so that each developer could pick what worked best for their software.
Vertical mirroring means that the two name tables are arranged side by side, and they repeat vertically. Horizontal mirroring means the 2 name tables are one on top of the other, and they repeat horizontally. Single-screen mirroring means that the same name table is repeated in all 4 slots, and the game usually gets to pick which one dynamically. 4-screen mirroring (i.e. no mirroring) means that the cartridge contains extra RAM for name tables and all 4 are unique.
Code: Select all
Vertical mirroring:
+---+---+
| A | B |
+---+---+
| A | B |
+---+---+
Horizontal mirroring:
+---+---+
| A | A |
+---+---+
| B | B |
+---+---+
1-screen mirroring:
+---+---+ +---+---+
| A | A | | B | B |
+---+---+ OR +---+---+
| A | A | | B | B |
+---+---+ +---+---+
4-screen mirroring:
+---+---+
| A | B |
+---+---+
| C | D |
+---+---+
That depends on how you want to code your scrolling engines. While all kinds of scrolling are possible on all types of mirroring, certain combinations result in scrolling artifacts in certain edges of the screen, so you might want to pick different mirroring configurations for parts that scroll differently in the same game, be it to minimize scrolling glitches or to simplify the engine itself.Is the change mirroring V / H in the code has some use?
Re: NESASM & AOROM Programming - a few questions
Sorry, Spelling error, I had to write AxROM, not UxROM.tokumaru wrote: Nope, U*ROM uses fixed vertical or horizontal mirroring.
tokumaru wrote: Did you try IFNDEF? NESASM's documentation says it has this directive. This block will only be processed if the label isn't defined yet, so it'll only be defined the first time the code is included. You should put the Reset, IRQ and NMI labels inside IFNDEF blocks like I said before, while internal labels can be temporary. To make sure that there's a global label separating the multiple instances of the included file you can just put a unique label before each include:
Code: Select all
EndOfBank0: .include "reset_nmi_irq_and_vectors.asm" (...) EndOfBank1: .include "reset_nmi_irq_and_vectors.asm" [/quote] I also used different labels, exactly the same error pops up. IFNDEF has a "syntax error" error. I probably do not know how to use this feature correctly.
Re: NESASM & AOROM Programming - a few questions
There's no way you'd be getting "Label multiply defined" if you used completely different labels each time. If you're including the same file multiple times, your defining the same labels multiple times.sdm wrote:I also used different labels, exactly the same error pops up.
Then keep trying to figure the syntax out... I don't know if a leading dot is required or something, but you have to figure the syntax out. Read the documentation, all the directives are there and that includes IFNDEF. It's not going to work if you can't figure out IFNDEF or some other tricky way to define labels.IFNDEF has a "syntax error" error. I probably do not know how to use this feature correctly.
Re: NESASM & AOROM Programming - a few questions
I am sending my AOROM test code, I do not know how to initialize this mapper.
- Attachments
-
- aorom_test_template_ b.zip
- (43.03 KiB) Downloaded 114 times
Last edited by sdm on Sat Aug 19, 2017 2:46 pm, edited 1 time in total.
Re: NESASM & AOROM Programming - a few questions
What "different instructions" would be needed to write to a '377 vs. a '161? Color Dreams uses a '377, and the only difference between it and GNROM (which uses a '161) is the nibble swapping (and the mapping of PRG A18-A17 to control the CIC stun).tokumaru wrote:To implement the selectable mirroring you'd have to steal one of the banking bits, so no, you can't make an AOROM-512 using a 4-bit register ('161 chip). You'd either need a second '161 or replace it with a larger register, which means different instructions.
Re: NESASM & AOROM Programming - a few questions
The wiring instructions are different for a different chip, right?
Re: NESASM & AOROM Programming - a few questions
One thing you seem to be doing wrong is putting the whole init code in the repeated bank, as well as the main loop. The repeated code should be a small stub, that calls the actual code that resides in other banks. Something like this:sdm wrote:I am sending my AOROM test code, I do not know how to initialize this mapper.
Code: Select all
.org $ff00 ;adjust this depending on how much code/data this file generates
.ifndef Reset
Reset:
.endif
lda #INIT_BANK
sta BankswitchTable+INIT_BANK ;switch bank
jmp Init ;go to real init code
.ifndef NMI
NMI:
.endif
pha ;save A
txa
pha ;save X
lda CurrentBank
pha ;save current bank number
lda #VBLANK_BANK
sta BankswitchTable+VBLANK_BANK ;switch bank
jsr VblankHandler ;call real handler
pla ;get previous bank number
tax
sta BankswitchTable, x ;restore previous bank
pla
tax ;restore X
pla ;restore Y
rti
.ifndef IRQ
IRQ:
.endif
rti
.ifndef CurrentBank
CurrentBank:
.endif
.DummyLocalSymbolToGetBankNumber:
.byte BANK(.DummyLocalSymbolToGetBankNumber)/4
.ifndef BankswitchTable
BankswitchTable:
.endif
.byte $00, $01, $02, $03, $04, $05, $06, $07
.org $fffa
.dw NMI
.dw Reset
.dw IRQ
I can't guarantee this code will work as is because I haven't tested it, there may be syntax errors and whatnot, but the basic idea of a stub section used with 32KB bankswitching is here.
Re: NESASM & AOROM Programming - a few questions
On a related note, you might want to load some code into the RAM to handle swapping PRGROM banks.
nesdoug.com -- blog/tutorial on programming for the NES
Re: NESASM & AOROM Programming - a few questions
You can, but I see very little reason to.
Re: NESASM & AOROM Programming - a few questions
Thanks. Thanks. I see that this is a lot more complicated mapper than UxROM.
How to correctly control the fourth bit Bank select register?
How to properly do it? In the end, this register is not a memory byte and do not know how to operate on separate bits in this case.
How to correctly control the fourth bit Bank select register?
Code: Select all
LDA #%00010000
STA Bank_TBL
LDA #%00000000
STA Bank_TBL
Re: NESASM & AOROM Programming - a few questions
When you write to AOROM's port, you have to write both the desired 32K bank and the desired nametable selection, OR'd together. GNROM, Color Dreams, and Holy Diver are similar: you have to update PRG, CHR, and (in the case of Holy Diver) mirroring in every write. If you're not changing a given bitfield, you need to write the same value to that bitfield that you wrote last time, much as with the bitfields that make up PPU control registers $2000 and $2001.