Skip to content

Instantly share code, notes, and snippets.

@matjam
Created September 26, 2025 07:53
Show Gist options
  • Select an option

  • Save matjam/d7b299483285e9c277781918a97d4873 to your computer and use it in GitHub Desktop.

Select an option

Save matjam/d7b299483285e9c277781918a97d4873 to your computer and use it in GitHub Desktop.
// the simplest MEGA65 test
.cpu _45gs02
* = $2001
.word basend // next BASIC line
.word 1206 // line #
.byte $fe,$02,$30 // BANK 0
.byte $3a,$9e // :SYS
.text toIntString(start)// address as string
.byte 0 // end of line
basend: .byte 0,0 // end of basic
// -------------------------------------------
* = $2011
start:
jsr initm65
lda #$00
sta $d021 // background: black
lda #$02
sta $d020 // border: red
// // Unlock VIC-IV registers
// lda #$47
// sta $d02f
// lda #$53
// sta $d02f
// Enable 80x50: H640 + V400, 80 cols, 50 rows
lda #$80
tsb $d031 // H640
lda #$08
tsb $d031 // V400
lda #$50
sta $d05e // CHRCOUNT = 80
lda #$32
sta $d07b // DISPROWS = 50
// Relocate screen to SCRPTR
lda SCRPTR+3
sta $d060 // LSB
lda SCRPTR+2
sta $d061 // MSB
lda SCRPTR+1
sta $d062 // BNK
lda SCRPTR+0
sta $d063 // MB low nibble
// Set color RAM to COLPTR
lda COLPTR+3
sta $d064 // COLPTRLSB
lda COLPTR+2
sta $d065 // COLPTRMSB
lda COLPTR+1
sta $d066 // COLPTRBNK
lda COLPTR+0
sta $d067 // COLPTRMB low nibble
// Pointers are set directly in data section below
// Clear entire 80x50 screen to spaces (and set colour white)
jsr clearscreen
jsr clearcolor
// Test: print pattern to see what's happening
lda #$01 // screen code for 'A'
ldx #$00 // offset 0
ldy #$00
jsr writescreen
lda #$02 // screen code for 'B'
ldx #$01 // offset 1
ldy #$00
jsr writescreen
lda #$03 // screen code for 'C'
ldx #$02 // offset 2
ldy #$00
jsr writescreen
// Test at offset 2000 (middle of screen: 25 * 80 = 2000)
lda #$04 // screen code for 'D'
ldx #$d0 // 2000 low byte
ldy #$07 // 2000 high byte
jsr writescreen
// Test at offset 100 (should be visible)
lda #$05 // screen code for 'E'
ldx #$64 // 100 low byte
ldy #$00 // 100 high byte
jsr writescreen
forever:
jmp forever
// routine to initialize the mega65
initm65:
// disallow Interrupts
sei
// force FAST mode (40.5 MHz)
lda #65
sta $00
// disable memory maps
lda #$00
tax
tay
taz
map
// Bank I/O in via C64 mechanism
lda #$35
sta $01
// enable VIC-IV via magic knock
lda #$47
sta $d02f
lda #$53
sta $d02f
// Unmap ROM via C65 mechanism
lda #0
sta $d030
// enable interrupts again
eom
rts
// -------------------------------------------------
// clearscreen: fill 4000 bytes starting at SCRNPTR with space ($20)
clearscreen:
lda #$00
sta cs_lo
sta cs_hi
cs_loop:
lda cs_lo
tax // X = offset lo
lda cs_hi
tay // Y = offset hi
lda #$20
jsr writescreen
// Increment counter first
inc cs_lo
bne cs_check
inc cs_hi
cs_check:
// Check if we've done 4000 bytes (0x0FA0)
// We want to clear 4000 bytes, so loop while < 0x0FA0
lda cs_hi
cmp #$0f
bcc cs_loop // if hi < 0x0F, continue
bne cs_done // if hi > 0x0F, done
lda cs_lo
cmp #$a0
bcc cs_loop // if hi == 0x0F and lo < 0xA0, continue
cs_done:
rts
cs_lo: .byte 0
cs_hi: .byte 0
// -------------------------------------------------
// clearcolor: fill 4000 bytes starting at COLPTR with white ($01)
clearcolor:
lda #$00
sta cc_lo
sta cc_hi
cc_loop:
lda cc_lo
tax // X = offset lo
lda cc_hi
tay // Y = offset hi
lda #$01 // white
jsr writecolor
// Increment counter first
inc cc_lo
bne cc_check
inc cc_hi
cc_check:
// Check if we've done 4000 bytes (0x0FA0)
lda cc_hi
cmp #$0f
bcc cc_loop // if hi < 0x0F, continue
bne cc_done // if hi > 0x0F, done
lda cc_lo
cmp #$a0
bcc cc_loop // if hi == 0x0F and lo < 0xA0, continue
cc_done:
rts
cc_lo: .byte 0
cc_hi: .byte 0
// -------------------------------------------------
// writecolor: Write color to color memory
// In: A = color, X = offset low, Y = offset high
writecolor:
pha
stx ofs_lo
sty ofs_hi
// Build 32-bit color pointer: COLPTR + offset
lda COLPTR+3
clc
adc ofs_lo
sta $f8
lda COLPTR+2
adc ofs_hi
sta $f9
lda COLPTR+1
adc #$00
sta $fa
lda COLPTR+0
adc #$00
sta $fb
ldz #$00
pla
sta (($f8)),z
rts
// -------------------------------------------------
// writescreen
// In: A = screen code, X = offset low, Y = offset high
// Uses 32-bit ZP indirect pointer at $FC..$FF
writescreen:
pha
stx ofs_lo
sty ofs_hi
// Build 32-bit screen pointer: SCRNPTR + offset
// Add 16-bit offset to 32-bit base address with proper carry handling
lda SCRPTR+3
clc
adc ofs_lo
sta $20
lda SCRPTR+2
adc ofs_hi
sta $21
lda SCRPTR+1
adc #$00
sta $22
lda SCRPTR+0
adc #$00
sta $23
// Use 32-bit indirect addressing with Z register
pla
ldz #$00
nop
sta (($20)),z
// Build 32-bit color pointer: COLPTR + offset
lda COLPTR+3
clc
adc ofs_lo
sta $24
lda COLPTR+2
adc ofs_hi
sta $25
lda COLPTR+1
adc #$00
sta $26
lda COLPTR+0
adc #$00
sta $27
lda #$01 // white
ldz #$00
sta (($24)),z
rts
ofs_lo: .byte 0
ofs_hi: .byte 0
// Screen and color pointers
SCRPTR: .byte $00,$04,$00,$00 // SCRNPTR = $0004.0000
COLPTR: .byte $00,$05,$00,$00 // COLPTR = $0005.0000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment