ASM6 templates

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

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

ASM6 templates

Post by tokumaru » Sat Mar 13, 2010 12:02 pm

Many people start out using NESASM, probably because of the tutorials that use it. And sometimes we suggest they use a better assembler, ASM6 being a good candidate because it's very simple to use. So I decided to put together these basic NROM and UNROM templates, so that there is no excuse for people not to try it.

Note that all of these shuld be assembld in the simplest possible way: asm6 game.asm game.nes

UPDATE: Included a CNROM template.

NROM template:

Code: Select all

;----------------------------------------------------------------
; constants
;----------------------------------------------------------------

PRG_COUNT = 1 ;1 = 16KB, 2 = 32KB
MIRRORING = %0001 ;%0000 = horizontal, %0001 = vertical, %1000 = four-screen

;----------------------------------------------------------------
; variables
;----------------------------------------------------------------

	.enum $0000

	;NOTE: declare variables using the DSB and DSW directives, like this:

	;MyVariable0 .dsb 1
	;MyVariable1 .dsb 3

	.ende

	;NOTE: you can also split the variable declarations into individual pages, like this:

	;.enum $0100
	;.ende

	;.enum $0200
	;.ende

;----------------------------------------------------------------
; iNES header
;----------------------------------------------------------------

	.db "NES", $1a ;identification of the iNES header
	.db PRG_COUNT ;number of 16KB PRG-ROM pages
	.db $01 ;number of 8KB CHR-ROM pages
	.db $00|MIRRORING ;mapper 0 and mirroring
	.dsb 9, $00 ;clear the remaining bytes

;----------------------------------------------------------------
; program bank(s)
;----------------------------------------------------------------

	.base $10000-(PRG_COUNT*$4000)

Reset:

	;NOTE: initialization code goes here

NMI:

	;NOTE: NMI code goes here

IRQ:

	;NOTE: IRQ code goes here

;----------------------------------------------------------------
; interrupt vectors
;----------------------------------------------------------------

	.org $fffa

	.dw NMI
	.dw Reset
	.dw IRQ

;----------------------------------------------------------------
; CHR-ROM bank
;----------------------------------------------------------------

	.incbin "tiles.chr"
UNROM template:

Code: Select all

;----------------------------------------------------------------
; constants
;----------------------------------------------------------------

MIRRORING = %0001 ;%0000 = horizontal, %0001 = vertical, %1000 = four-screen

;----------------------------------------------------------------
; variables
;----------------------------------------------------------------

	.enum $0000

	;NOTE: declare variables using the DSB and DSW directives, like this:

	;MyVariable0 .dsb 1
	;MyVariable1 .dsb 3

	.ende

	;NOTE: you can also split the variable declarations into individual pages, like this:

	;.enum $0100
	;.ende

	;.enum $0200
	;.ende

;----------------------------------------------------------------
; iNES header
;----------------------------------------------------------------

	.db "NES", $1a ;identification of the iNES header
	.db $08 ;number of 16KB PRG-ROM pages
	.db $00 ;number of 8KB CHR-ROM pages
	.db $20|MIRRORING ;mapper 2 and mirroring
	.dsb 9, $00 ;clear the remaining bytes

;----------------------------------------------------------------
; program bank 0
;----------------------------------------------------------------

	.base $8000

	;NOTE: contents of program bank 0 go here

	.org $c000

;----------------------------------------------------------------
; program bank 1
;----------------------------------------------------------------

	.base $8000

	;NOTE: contents of program bank 1 go here

	.org $c000

;----------------------------------------------------------------
; program bank 2
;----------------------------------------------------------------

	.base $8000

	;NOTE: contents of program bank 2 go here

	.org $c000

;----------------------------------------------------------------
; program bank 3
;----------------------------------------------------------------

	.base $8000

	;NOTE: contents of program bank 3 go here

	.org $c000

;----------------------------------------------------------------
; program bank 4
;----------------------------------------------------------------

	.base $8000

	;NOTE: contents of program bank 4 go here

	.org $c000

;----------------------------------------------------------------
; program bank 5
;----------------------------------------------------------------

	.base $8000

	;NOTE: contents of program bank 5 go here

	.org $c000

;----------------------------------------------------------------
; program bank 6
;----------------------------------------------------------------

	.base $8000

	;NOTE: contents of program bank 6 go here

	.org $c000

;----------------------------------------------------------------
; fixed program bank (7)
;----------------------------------------------------------------

	.base $c000

Reset:

	;NOTE: initialization code goes here

NMI:

	;NOTE: NMI code goes here

IRQ:

	;NOTE: IRQ code goes here

;----------------------------------------------------------------
; interrupt vectors
;----------------------------------------------------------------

	.org $fffa

	.dw NMI
	.dw Reset
	.dw IRQ
CNROM Template:

Code: Select all

;----------------------------------------------------------------
; constants
;----------------------------------------------------------------

PRG_COUNT = 2 ;1 = 16KB, 2 = 32KB
CHR_COUNT = 4 ;1 = 8KB, 2 = 16KB, 4 = 32KB
MIRRORING = %0001 ;%0000 = horizontal, %0001 = vertical, %1000 = four-screen

;----------------------------------------------------------------
; variables
;----------------------------------------------------------------

	.enum $0000

	;NOTE: declare variables using the DSB and DSW directives, like this:

	;MyVariable0 .dsb 1
	;MyVariable1 .dsb 3

	.ende

	;NOTE: you can also split the variable declarations into individual pages, like this:

	;.enum $0100
	;.ende

	;.enum $0200
	;.ende

;----------------------------------------------------------------
; iNES header
;----------------------------------------------------------------

	.db "NES", $1a ;identification of the iNES header
	.db PRG_COUNT ;number of 16KB PRG-ROM pages
	.db CHR_COUNT ;number of 8KB CHR-ROM pages
	.db $30|MIRRORING ;mapper 3 and mirroring
	.dsb 9, $00 ;clear the remaining bytes

;----------------------------------------------------------------
; program bank(s)
;----------------------------------------------------------------

	.base $10000-(PRG_COUNT*$4000)

Reset:

	;NOTE: initialization code goes here

NMI:

	;NOTE: NMI code goes here

IRQ:

	;NOTE: IRQ code goes here

;----------------------------------------------------------------
; interrupt vectors
;----------------------------------------------------------------

	.org $fffa

	.dw NMI
	.dw Reset
	.dw IRQ

;----------------------------------------------------------------
; CHR-ROM banks
;----------------------------------------------------------------

	.incbin "tiles0.chr"
	.incbin "tiles1.chr"
	.incbin "tiles2.chr"
	.incbin "tiles3.chr"
Last edited by tokumaru on Tue May 25, 2010 9:43 am, edited 1 time in total.

User avatar
Banshaku
Posts: 2328
Joined: Tue Jun 24, 2008 8:38 pm
Location: Fukuoka, Japan
Contact:

Post by Banshaku » Sat Mar 13, 2010 6:28 pm

I have a question regarding ASM6. For the sake of the sample, all the banks were defined in a single file but is it possible to define them in a different one and include them? I guess you can, just don't know yet about this assembler.

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Sat Mar 13, 2010 6:51 pm

Banshaku wrote:For the sake of the sample, all the banks were defined in a single file but is it possible to define them in a different one and include them? I guess you can, just don't know yet about this assembler.
Yes, you can put whatever you want in separate files and include them, it's the same as if it was all part of a single file.

I keep everything separate myself, and nest several levels of includes (master file includes bank files which include functions which include tables, stuff like that), but I made the examples as single files for the sake of simplicity, as most people start out with single files.

User avatar
GradualGames
Posts: 1107
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Post by GradualGames » Sat Mar 13, 2010 8:36 pm

When I tried to break my program into multiple files when it was still written for ASM6, I had trouble with dependencies between modules. Is there a way to "forward declare" a label before it is actually defined and used? CA65 resolved this issue for me quite nicely with the ability to export and import symbols, in conjunction with the LD65 linker. I also like the fact that CA65 abstracts out all of the .base, and .pad directives one normally needs to do in an assembler such as ASM6. You can describe all of that in one concise config file, and then all your source files do is name segments that you mapped out in your config file.

BTW, I think perhaps these templates ought to be stickied or wikied, or both. And perhaps a CA65 developer could upload a template for a simple NROM or UNROM project, including a config file, source file and makefile (not that makefiles are absolutely necessary, but it appears to be a common way CA65 users build their projects).

*edit* I actually still use ASM6. When I'm testing some feature I don't understand how to use yet, I don't really want to bother with multiple files. As far as I know, CA65 doesn't have the equivalent of .org, .base or .pad within a source file, you can only do these things within the config file with memory areas, segments, and the attribute "fill = yes or no."

User avatar
koitsu
Posts: 4216
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Post by koitsu » Sat Mar 13, 2010 9:51 pm

Gradualore wrote:Is there a way to "forward declare" a label before it is actually defined and used?
Comment in passing: the commonly-used term in programming for this is "prototyping". The Wikipedia article describes functions, but variable prototypes work the same way.

Most assemblers I've used over the years are multi-pass, which during their initial pass take note of all (global) labels and equates.

User avatar
loopy
Posts: 394
Joined: Sun Sep 19, 2004 10:52 pm
Location: UT

Post by loopy » Sat Mar 13, 2010 10:26 pm

It isn't necessary to declare a label before using it. ASM6 is a multi-pass assembler. It'll take as many passes as it needs to resolve unknown symbols.

yassergsNESDEV
Posts: 3
Joined: Fri Apr 09, 2010 7:06 am

Post by yassergsNESDEV » Fri Apr 09, 2010 8:32 am

Ok, I got NESASM but I have not any tutorials. Where I can find some.. from the beginning to advanced mode

jbuonacc
Posts: 14
Joined: Mon Mar 29, 2010 9:25 am
Location: Rochester, NY

Post by jbuonacc » Fri Apr 09, 2010 8:38 am

yassergsNESDEV wrote:Ok, I got NESASM but I have not any tutorials. Where I can find some.. from the beginning to advanced mode
http://nintendoage.com/forum/messagevie ... eadid=7155

doesn't get too advanced, but the basics are covered pretty well.

User avatar
tokumaru
Posts: 11469
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Tue May 25, 2010 9:45 am

Added a CNROM template.

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Mon May 30, 2011 8:15 am

tokumaru, so far I have a main file, a prg file, a chr file, and a vblank file. Where should I place famitone.asm? In what address space can I put a bunch of .incsrcs? You seem to be the best person to ask; you understand how rom files should be put together. :)

UncleSporky
Posts: 385
Joined: Sat Nov 17, 2007 8:44 pm

Post by UncleSporky » Mon May 30, 2011 10:51 am

You can insert extra code anywhere before you .pad $FFFA and set up the interrupts. Most of the time you only have chr data after that point.

Here's how my simple project is set up:

I have a batch file, make.bat, that runs asm6 and compiles my project. This is all it contains:

Code: Select all

asm6 header.asm demo.nes demo.txt
Then header.asm contains the rest of the project info:

Code: Select all

;iNES header

.db "NES",$1a 		;iNES identifier

.db $01			;number of PRG-ROM blocks

.db $01			;number of CHR-ROM blocks

.db $00, $00		;ROM control bytes: Horizontal mirroring, no SRAM or trainer, Mapper #0

.db $00,$00,$00,$00,$00,$00,$00,$00	;filler

;PRG-ROM

.include "main.asm"
.include "famitone.asm"	;FamiTone audio driver by Shiru
.include "music.asm"	;sample music data

.pad $FFFA		;fill any remaining space with zeroes
.dw vblank,reset,irq	;set interrupt addresses (defined in main.asm)

;CHR-ROM

.incbin "main.chr"
My whole program is inside main.asm, and then I simply inserted famitone and sample music after that. This is also the place to include data tables, screen data, anything else that isn't code but also isn't graphics.

If you set it up the way I have it above, make sure that your main, prg and vblank files don't have the .pad $FFFA and .dw vblank,reset,irq anywhere in them. In my project I moved it up to this broader level to make sure it comes after everything else.

Also make sure you aren't duplicating that iNES header info anywhere else either.

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Mon May 30, 2011 11:17 am

Thank you UncleSporky :D that's very helpfull to me!

UncleSporky wrote:If you set it up the way I have it above, make sure that your main, prg and vblank files don't have the .pad $FFFA and .dw vblank,reset,irq anywhere in them. In my project I moved it up to this broader level to make sure it comes after everything else.
There is chr after it... in mine too. Does the chr not matter because it's in the PPU's memory? (and it's not in the CPU's memory? :?)

UncleSporky
Posts: 385
Joined: Sat Nov 17, 2007 8:44 pm

Post by UncleSporky » Mon May 30, 2011 4:35 pm

Oh, when I said "after everything else" I meant except for chr. :)

chr always goes right after the interrupt addresses. It's good to learn why at some point, but for now it might be easiest just to remember it that way. iNES header -> define variables -> code -> data tables -> interrupt addresses -> chr data.

You don't have chr data if your game uses CHR RAM, but you're not dealing with that yet.

Basically, the interrupt addresses always start at $FFFA and end at $FFFF. The next step up would be $10000, but you have no way to refer to this location directly because it's more than two bytes long. Instead, the NES just assumes that's where the graphics are located and you have to refer to them through other methods (using PPU IDs and registers).

Deemar
Posts: 15
Joined: Thu Jun 25, 2015 9:16 pm
Location: Calgary, Alberta

Re: ASM6 templates

Post by Deemar » Thu Jul 23, 2015 10:46 pm

I'm super new to Assembly, what are these templates for exactly? If it's a template for making a NES game, why is there more than one? Thanks.

User avatar
Prime
Posts: 32
Joined: Sun Sep 21, 2014 10:18 pm

Re: ASM6 templates

Post by Prime » Thu Jul 23, 2015 10:53 pm

tokumaru templates are all different

Each one starts with him telling people

NROM template:

UNROM template:

CNROM Template:

Post Reply