NES Hello World Aug 7, 2011
The program below is written for xa65, a 6502/R65C02/65816 cross-assembler. It should be portable to other 6502 assemblers with minor tweaks. (The xa65 website is down as of the time of writing, but the program can be found in many places on the web, or from your friendly neighborhood Linux distro's package system.)
The $200X addresses used below are magic registers which control the NES's video memory. See NES PPU for details on their function, and for some brief info on how images are stored in the NES. (It's complicated.)
This program eschews the normal method of storing graphics in ROM (called CHR-ROMs) in favor of copying the graphics from PRG-ROM into CHR-RAM. There is not really a good reason for this, except you have to deal with fewer bank files.
; load this at $8000 * = $8000 ; Graphics data. ; Each line is a character: ; space H E L O , W R D ! chrdata: .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .byte 0,102,102,126,102,102,102,0,0,0,0,0,0,0,0,0 .byte 0,126,96,120,96,96,126,0,0,0,0,0,0,0,0,0 .byte 0,96,96,96,96,96,126,0,0,0,0,0,0,0,0,0 .byte 0,60,102,102,102,102,60,0,0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,24,24,48,0,0,0,0,0,0,0,0 .byte 0,102,102,102,102,126,102,0,0,0,0,0,0,0,0,0 .byte 0,124,102,124,120,108,102,0,0,0,0,0,0,0,0,0 .byte 0,124,102,102,102,102,124,0,0,0,0,0,0,0,0,0 .byte 0,24,24,24,24,0,24,0,0,0,0,0,0,0,0,0 .byte $ff ; The message "Hello, World!", ; chosen from the characters above. message: .byte 1,2,3,3,4,5,0,6,4,7,3,8,9,$ff ; Colors palette: .byte 13,32,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 ; the beginning int_reset: ; load graphics data into CHR-RAM lda #0 sta $2006 sta $2006 ldx #0 ldc: lda chrdata,x cmp #$ff beq cdone sta $2007 inx jmp ldc cdone: ; write the message to the name table lda #$20 sta $2006 sta $2006 ldx #0 ldm: lda message,x cmp #$ff beq mdone sta $2007 inx jmp ldm mdone: ; load the palette lda #$3f sta $2006 lda #$00 sta $2006 ldx #0 ldp: lda palette,x sta $2007 inx cpx #$10 bne ldp ; reset PPU pointer ; (otherwise everything is offset) lda #0 sta $2006 sta $2006 ; enable PPU lda #%10001000 sta $2000 lda #%00011110 sta $2001 ; done, just wait around main: jmp main ; these interrupts aren't needed for this program int_vblank: int_irqbrk: rti ; fill the rest of this bank with zeroes .dsb $bffa-*, 0 ; except for the interrupt vectors .word int_vblank, int_reset, int_irqbrk
To get the above code to work in an emulator, just assembling it isn't quite enough. You need to wrap it with a header that gives the emulator a little more information about your program. This is beyond the scope of this writeup.
H4sIAF2cPk4AA+3QIQ7CMBTG8Y4NBoIE2UBCegQOQAIGt2C4wFQVB0AsS+cwOwS4Kk5A0DiOAA6J QY+OBLYZFPL/S833Xt9r0uViNfTED1qnWusqp/EmjtMqx6VanrrbetrcIeWktq/cWPUSnWzWjewk 9VkphfzGwmv5ftAWnSD0u72ir5ovWZF3lDt7cRTmXDzCPFT36Gys+tZ3Vf1m7MwV30OuczBl9Tq4 PD9r7DYXyo5zT0Uym//6JgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/mOUncwoewEUtjtMEEAAAA==
raincomplex says haha, indeed. although, going that route, you may as well use the C64
Pseudo_Intellectual says Fair enough, though the C64 won't come pre-loaded with Donkey Kong sprites to dance while you greet the world 8)