👾 Moving Rainbow in 6502 Assembly
I’ve been wanting to get into assembly language forever but haven’t found a way to iterate and test in a satisfying way to makes learning for me really easy. Recently, I saw flame from aeriform.io had developed the Minicube64, which is a fantasy console based on the 6502.
The 6502 is the same chip that was found in early Commodores, the BBC Micro, the NES/Famicom, the Apple ][, and zillions of others. It’s a simplified amount of assembly instructions, which lends itself to picking it up much more easily and quickly than would be possible with a more expansive set like on modern processors. Perfect.
After installing Minicube64, I did a tutorial, read a ton of reference materials, and took some notes while going through some of the demo files.
Not too far after this, I saw that a gamejam for the Minicube64 was being held at itch.io and I set out to have a rainbow render on the screen, and if possible, animate it left to right. This felt like a manageable goal and through a LOT of trial and error, was finally able to get there.
This is the code 👇
include "64cube.inc" ; Include the helper functions ENUM $0 ; Enumerate values starting at $0000 initColor rBYTE 1 ; set initColor as 1 byte ENDE ; End enumeration org $200 ; Set program origin to $0200 sei ; Set interrupt disable flag ; Set the stack pointer to be #$ff (low bits of $0100-01ff) ldx #$ff ; Load value $ff into X txs ; Transfer value of X into the stack ; pointer ; Set the video buffer page in the $f000 page in memory lda #$f ; Load high byte of page into A ; register sta VIDEO ; Store value in A at 'VIDEO' ; Set the colors buffer page in the $5000 page in memory lda #$5 ; Load highbyte of page into 'a' ; register sta COLORS ; Store value in A at 'COLORS' _setw IRQ, VBLANK_IRQ ; Set value of VBLANK_IRQ to address of ; 'IRQ' label cli ; Clear interrupt disable flag Infinite: ; Set 'Infinite' label dec initColor ; Decrement initColor lda initColor ; Load initColor into A and #$3f ; Ensure A never goes above #$3f jsr Draw ; Jump to 'Draw' subroutine jmp Infinite ; Create infinite loop IRQ: ; Set 'IRQ' label rti ; Return from interrupt Draw: ; Set 'Draw' label ; This will draw a column of each color from one end of the color spectrum to ; the other. Eventually, I hope to have this scale from left to right with ; animation. ; ; A = Address of color within the COLORS page ; X = Col counter (ff-00: ff being the last col of the last row within the ; four subrows, 00 being the first col of the first row in the subrows ; Y = Row counter (ff-f0: ff being the last four subrows, ff being the first) ldx #$0 ; Initialize column counter (X) ldy #$f ; Initialize row counter (Y) Loop: lda initColor ; Set accumulator to color value SubLoop: ; Create a subloop label and #$3f ; Ensure A never goes above #$3f sta $f000,X ; Store A in video page plus X for sta $f100,X ; all columns sta $f200,X sta $f300,X sta $f400,X sta $f500,X sta $f600,X sta $f700,X sta $f800,X sta $f900,X sta $fa00,X sta $fb00,X sta $fc00,X sta $fd00,X sta $fe00,X sta $ff00,X sec ; Set carry flag to wrangle SBC sbc #1 ; Decrement the color value dex ; Decrement column counter (X) bne SubLoop ; If color value is not zero, go to subloop dex ; Decrement col counter (X) dey ; Decrement row counter (Y) bne Loop ; If Y is not zero, go to Loop rts ; Else return from the subroutine Palette: ; Set 'Palette' label ; This will set the palette of colors available in the COLORS page, enumerating ; from $00 upward within that page. org $0500 ; Set program origin to $0500 hex FF0000 ; Set these colors in colors page hex FF1500 hex FF2F00 hex FF4400 hex FF5E00 hex FF7700 hex FF8C00 hex FFA600 hex FFBF00 hex FFD500 hex FFEE00 hex FBFF00 hex E1FF00 hex C8FF00 hex B3FF00 hex 99FF00 hex 80FF00 hex 6AFF00 hex 51FF00 hex 3CFF00 hex 22FF00 hex 09FF00 hex 00FF0D hex 00FF26 hex 00FF40 hex 00FF55 hex 00FF6E hex 00FF84 hex 00FF9D hex 00FFB7 hex 00FFCC hex 00FFE5 hex 00FFFF hex 00EAFF hex 00D0FF hex 00BBFF hex 00A2FF hex 0088FF hex 0073FF hex 0059FF hex 0040FF hex 002AFF hex 0011FF hex 0400FF hex 1E00FF hex 3700FF hex 4C00FF hex 6600FF hex 8000FF hex 9500FF hex AE00FF hex C300FF hex DD00FF hex F700FF hex FF00F2 hex FF00D9 hex FF00BF hex FF00AA hex FF0090 hex FF007B hex FF0062 hex FF0048 hex FF0033 hex FF0019
I’ve added quite a bit of annotation to this, but will probably dig into it more in depth at a later date. To get it running:
- install Minicube64
- create a new file called
rainbow.sand put the above contents within it
- run this in your shell: