NESASM & AOROM Programming - a few questions

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

sdm
Posts: 412
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

NESASM & AOROM Programming - a few questions

Post by sdm »

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
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM & AOROM Programming - a few questions

Post by tokumaru »

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?
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).
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).
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.

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
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?)
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.
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).
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.

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.
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".
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.
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
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.
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: NESASM & AOROM Programming - a few questions

Post by dougeff »

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
sdm
Posts: 412
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

Re: NESASM & AOROM Programming - a few questions

Post by sdm »

tokumaru 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.
I tried
.include "reset_code.asm"
In every bank and unfortunately pops up '' Label multiply defined" : /
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:
It probably also will not work with NESASM3.

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?
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.
I will probably be forced to do this some time later..
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM & AOROM Programming - a few questions

Post by tokumaru »

sdm wrote:I tried
.include "reset_code.asm"
In every bank and unfortunately pops up '' Label multiply defined" : /
Yeah, if you don't do anything about the labels, that's expected.
It probably also will not work with NESASM3.
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"

(...)
Also, keep in mind that NESASM bank numbers are not a direct match to A*ROM bank numbers, so you have to put your include every 4 NESASM banks (i.e. banks 3, 7, 11, 15, etc.).
I just noticed that UxROM only has Single-screen mirroring.
Nope, U*ROM uses fixed vertical or horizontal mirroring.
So the first and second NameTable in 2KB VRAM are exactly the same? I do not quite understand the meaning of this use.
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.

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 |
+---+---+
Is the change mirroring V / H in the code has some use?
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.
sdm
Posts: 412
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

Re: NESASM & AOROM Programming - a few questions

Post by sdm »

tokumaru wrote: Nope, U*ROM uses fixed vertical or horizontal mirroring.
Sorry, Spelling error, I had to write AxROM, not UxROM.

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.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM & AOROM Programming - a few questions

Post by tokumaru »

sdm wrote:I also used different labels, exactly the same error pops up.
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.
IFNDEF has a "syntax error" error. I probably do not know how to use this feature correctly.
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.
sdm
Posts: 412
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

Re: NESASM & AOROM Programming - a few questions

Post by sdm »

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.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: NESASM & AOROM Programming - a few questions

Post by tepples »

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.
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).
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM & AOROM Programming - a few questions

Post by tokumaru »

The wiring instructions are different for a different chip, right?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM & AOROM Programming - a few questions

Post by tokumaru »

sdm wrote:I am sending my AOROM test code, I do not know how to initialize this mapper.
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:

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 hope this gives you a better idea of what the include file has to contain, but I can't fix your whole code for you. If there's something you don't understand, pleas ask here, but it's important that you understand what's going on.

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.
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: NESASM & AOROM Programming - a few questions

Post by dougeff »

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
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: NESASM & AOROM Programming - a few questions

Post by tokumaru »

You can, but I see very little reason to.
sdm
Posts: 412
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

Re: NESASM & AOROM Programming - a few questions

Post by sdm »

Thanks. Thanks. I see that this is a lot more complicated mapper than UxROM.

How to correctly control the fourth bit Bank select register?

Code: Select all

	LDA #%00010000
	STA Bank_TBL

	LDA #%00000000
	STA Bank_TBL
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.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: NESASM & AOROM Programming - a few questions

Post by tepples »

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.
Post Reply