Hey Everybody!
Summer vacation from college hit, and now I have some time to tackle some new fun projects. The top on the list is to learn some embedded systems, and I figured I would start with the good old fashioned NES. At the moment I am only interested in learning and writing roms (not emulators themselves). Perhaps in the future my interests will expand.
As I muddled through NES documentation last week, I hit the same problem that everybody has written about in a number of posts - There is very good documentation, but no comprehensive single source, especially on the level of noobs like me. At about day 3 I said to myself "If I ever figure this stuff out, I'd like to write a good guide to NES programming." Of course that's more in the pipe-dream phase right now, as I have yet to learn NES programming, learn it WELL, and then have time (provided I don't get tired of the subject) to write such a tome. It's a nice idea, who knows. Perhaps I'll fizzle out 2 weeks from now and never come back to NES programming. However at the moment I'm very optimistic, and hope I don't lose the passion before I can contribute something.
My ideas for approaching writing a tutorial are a little different. At a first glimpse (and I don't know much mind you) I would suggest:
6502 Programming
A basic (VERY VERY BASIC, barely applicable to programming) overview of NES architecture. More of a fun read than educational.
Basic PPU programming (with pre-supplied iNes headers, register pre-sets, and maybe even chr-roms)
A look into the chr-rom format.
Sprites and animation.
Standard Control Pad programming
Basic game design and theory (supply exercises to make small games)
Intermediate PPU programming (explanation of register presets, iNes headers, scrolling, palettes)
Sound
Advanced PPU programming (the rest)
Advanced Control programming (light gun, power pad, etc.)
I don't know enough to explicitly detail the concepts in order, but the main difference in approaches is to get the user programming quickly in a pre-defined environment without having them get bored or confused with the wealth of information that people have to shuffle through at the moment to learn how to get a simple pattern on the screen.
I looked through most all of the posts in the NESdev subsection of this site, and it seems like a nice community, albiet a tough one to get into. There's no way I can avoid being a noob for now, but I hope you don't hold it against me. The question I'm about to pose seems really silly, yet I've spent 2 full days reading through Yoshi's 1.0 and 2.0 docs, Marat Fayzullin's doc, Patrick Diskin's doc, and a couple of others trying to figure it out. I even read some retard's ultimate NES programming guide that only had 6502 op codes in it, with "NES PROGRAMMING: TO BE WRITTEN" at the end (and a thank you note to some other guy for giving him the op codes). Still no dice for me. I hope you don't take me as one of those "d00d I WANT TO MAD HAXOR THE NES LOL ROFLROXORS BUT WHAT THE CRAP IS 6250 ASSEMBLY YO?" people. I have done a bit of research, and am still stumped.
What I'm using:
NESAsm 2.51 (don't know if there's a better version out)
NES-CHR-ROM Creator 1.1
FCEU 0.98.12
I'm designing with NTSC in mind.
I saw that some people noted NESAsm as the "n00b" assembler, and a number of other opinions on chr-rom editors. I'm very open to suggestions, as I really have no clue what I'm doing.
And if I haven't bored you yet, on with the question!
I keep seeing a purple block in the upper left hand corner of the screen. In PAL mode it's horribly noticeable (I don't care much because I'm looking to do NTSC), but in NTSC mode it's still noticeable as a small line (the very bottom of the square still shows). What is this artifact? Is it something I shouldn't worry about? Is it a result of a poor memory write? Is it my emulator? Grr....
Here is a picture of a cheap demo program that draws a bunch of unhappy faces. This is in PAL mode (Just to make it more obvious in the picture, though it is still somewhat noticeable in NTSC).
And here is a file containing my source:
http://www.geocities.com/thereallucky/ericnes.zip
I suppose my source is short enough to show here if you like...
; One programming bank
; One chr rom
;
.inesprg 1
.ineschr 1
; I have no clue yet as to what inesmir and inesmap do.
; Note: Read Neshdr.doc
.inesmir 1
.inesmap 0
.org $8000
.bank 0
Start:
; Set up the PPU registers!
; PPU Register #1
; D7 - Execute NMI on VBlank is DISABLED
; D6 - Unused.
; D5 - Sprite size is 8x8
; D4 - Background Pattern Table Address is $0000
; D3 - Sprite Pattern Table ADdress is $1000
; D2 - PPU Address Increment is 1
; D1:D0 = Nametable Address to use is $2000
lda #%00001000
sta $2000
; PPU Register #2
; D7:D5 - (Color display determined by D0)
; D7:D5 - No color intensity
; D4 - Sprites VISIBLE
; D3 - Background VISIBLE
; D2 - NO Sprite Clipping
; D1 - NO Background Clipping
; D0 - Color Display (Effects D7:D5 function)
lda #%00011110
sta $2001
waitVBlank:
lda $2002
bpl waitVBlank
; **** THIS SECTION LOADS UP THE PALETTE ****
; Time to write to the palette,
; starting at $3F00
lda #$3F
sta $2006
lda #$00
sta $2006
ldx #$00
loadPalette:
lda palette,x
sta $2007
inx
cpx #$20
bne loadPalette
; **** FINISHED LOADING UP THE PALETTE ****
; **** DRAW A BUNCH OF UNHAPPY FACES TO THE SCREEN ****
; We want to store data into the PPU's
; memory at $2000. We set up the register at $2006.
;
; This sets our starting point on the background 32x30
; grid. $2000 is the very upper left of the screen.
lda #$20
sta $2006
lda #$00
sta $2006
; We want to draw 7 rows of unhappy faces,
; which ends up being 224 unhappy faces.
; X will be our counter, so let's set it to 224
; in preparation for a countdown loop.
ldx #$E0
drawPattern:
lda #$01
sta $2007
dex
bne drawPattern
; **** FINISHED DRAWING UNHAPPY FACES ****
Loop:
jmp Loop
palette:
; Image Palette
.db $32,$01,$06,$2A,$32,$03,$10,$00
.db $32,$38,$33,$3C,$32,$21,$26,$02
; Sprite Palette
.db $32,$16,$12,$14,$32,$07,$17,$27
.db $32,$0B,$07,$2D,$32,$3A,$35,$31
.bank 1
.org $FFFA
.dw 0 ; NMI_Routine
.dw Start ; Reset_Routine
.dw 0 ; IRQ_Routine
.bank 2
.org $0000
.incbin "eric.chr"
**** END OF FILE *****
If you can tell me what I'm doing wrong, me love you long time.
PEACE!
-Eric
Summer vacation from college hit, and now I have some time to tackle some new fun projects. The top on the list is to learn some embedded systems, and I figured I would start with the good old fashioned NES. At the moment I am only interested in learning and writing roms (not emulators themselves). Perhaps in the future my interests will expand.
As I muddled through NES documentation last week, I hit the same problem that everybody has written about in a number of posts - There is very good documentation, but no comprehensive single source, especially on the level of noobs like me. At about day 3 I said to myself "If I ever figure this stuff out, I'd like to write a good guide to NES programming." Of course that's more in the pipe-dream phase right now, as I have yet to learn NES programming, learn it WELL, and then have time (provided I don't get tired of the subject) to write such a tome. It's a nice idea, who knows. Perhaps I'll fizzle out 2 weeks from now and never come back to NES programming. However at the moment I'm very optimistic, and hope I don't lose the passion before I can contribute something.
My ideas for approaching writing a tutorial are a little different. At a first glimpse (and I don't know much mind you) I would suggest:
6502 Programming
A basic (VERY VERY BASIC, barely applicable to programming) overview of NES architecture. More of a fun read than educational.
Basic PPU programming (with pre-supplied iNes headers, register pre-sets, and maybe even chr-roms)
A look into the chr-rom format.
Sprites and animation.
Standard Control Pad programming
Basic game design and theory (supply exercises to make small games)
Intermediate PPU programming (explanation of register presets, iNes headers, scrolling, palettes)
Sound
Advanced PPU programming (the rest)
Advanced Control programming (light gun, power pad, etc.)
I don't know enough to explicitly detail the concepts in order, but the main difference in approaches is to get the user programming quickly in a pre-defined environment without having them get bored or confused with the wealth of information that people have to shuffle through at the moment to learn how to get a simple pattern on the screen.
I looked through most all of the posts in the NESdev subsection of this site, and it seems like a nice community, albiet a tough one to get into. There's no way I can avoid being a noob for now, but I hope you don't hold it against me. The question I'm about to pose seems really silly, yet I've spent 2 full days reading through Yoshi's 1.0 and 2.0 docs, Marat Fayzullin's doc, Patrick Diskin's doc, and a couple of others trying to figure it out. I even read some retard's ultimate NES programming guide that only had 6502 op codes in it, with "NES PROGRAMMING: TO BE WRITTEN" at the end (and a thank you note to some other guy for giving him the op codes). Still no dice for me. I hope you don't take me as one of those "d00d I WANT TO MAD HAXOR THE NES LOL ROFLROXORS BUT WHAT THE CRAP IS 6250 ASSEMBLY YO?" people. I have done a bit of research, and am still stumped.
What I'm using:
NESAsm 2.51 (don't know if there's a better version out)
NES-CHR-ROM Creator 1.1
FCEU 0.98.12
I'm designing with NTSC in mind.
I saw that some people noted NESAsm as the "n00b" assembler, and a number of other opinions on chr-rom editors. I'm very open to suggestions, as I really have no clue what I'm doing.
And if I haven't bored you yet, on with the question!
I keep seeing a purple block in the upper left hand corner of the screen. In PAL mode it's horribly noticeable (I don't care much because I'm looking to do NTSC), but in NTSC mode it's still noticeable as a small line (the very bottom of the square still shows). What is this artifact? Is it something I shouldn't worry about? Is it a result of a poor memory write? Is it my emulator? Grr....
Here is a picture of a cheap demo program that draws a bunch of unhappy faces. This is in PAL mode (Just to make it more obvious in the picture, though it is still somewhat noticeable in NTSC).
And here is a file containing my source:
http://www.geocities.com/thereallucky/ericnes.zip
I suppose my source is short enough to show here if you like...
; One programming bank
; One chr rom
;
.inesprg 1
.ineschr 1
; I have no clue yet as to what inesmir and inesmap do.
; Note: Read Neshdr.doc
.inesmir 1
.inesmap 0
.org $8000
.bank 0
Start:
; Set up the PPU registers!
; PPU Register #1
; D7 - Execute NMI on VBlank is DISABLED
; D6 - Unused.
; D5 - Sprite size is 8x8
; D4 - Background Pattern Table Address is $0000
; D3 - Sprite Pattern Table ADdress is $1000
; D2 - PPU Address Increment is 1
; D1:D0 = Nametable Address to use is $2000
lda #%00001000
sta $2000
; PPU Register #2
; D7:D5 - (Color display determined by D0)
; D7:D5 - No color intensity
; D4 - Sprites VISIBLE
; D3 - Background VISIBLE
; D2 - NO Sprite Clipping
; D1 - NO Background Clipping
; D0 - Color Display (Effects D7:D5 function)
lda #%00011110
sta $2001
waitVBlank:
lda $2002
bpl waitVBlank
; **** THIS SECTION LOADS UP THE PALETTE ****
; Time to write to the palette,
; starting at $3F00
lda #$3F
sta $2006
lda #$00
sta $2006
ldx #$00
loadPalette:
lda palette,x
sta $2007
inx
cpx #$20
bne loadPalette
; **** FINISHED LOADING UP THE PALETTE ****
; **** DRAW A BUNCH OF UNHAPPY FACES TO THE SCREEN ****
; We want to store data into the PPU's
; memory at $2000. We set up the register at $2006.
;
; This sets our starting point on the background 32x30
; grid. $2000 is the very upper left of the screen.
lda #$20
sta $2006
lda #$00
sta $2006
; We want to draw 7 rows of unhappy faces,
; which ends up being 224 unhappy faces.
; X will be our counter, so let's set it to 224
; in preparation for a countdown loop.
ldx #$E0
drawPattern:
lda #$01
sta $2007
dex
bne drawPattern
; **** FINISHED DRAWING UNHAPPY FACES ****
Loop:
jmp Loop
palette:
; Image Palette
.db $32,$01,$06,$2A,$32,$03,$10,$00
.db $32,$38,$33,$3C,$32,$21,$26,$02
; Sprite Palette
.db $32,$16,$12,$14,$32,$07,$17,$27
.db $32,$0B,$07,$2D,$32,$3A,$35,$31
.bank 1
.org $FFFA
.dw 0 ; NMI_Routine
.dw Start ; Reset_Routine
.dw 0 ; IRQ_Routine
.bank 2
.org $0000
.incbin "eric.chr"
**** END OF FILE *****
If you can tell me what I'm doing wrong, me love you long time.
PEACE!
-Eric