Milo Land

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.

flame from aeriform.io

Minicube64

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.

6502 tutorial

6502 reference materials

Minicube64 notes

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.

Jam on itch.io

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 from Github

Install Minicube64 from itch.io