6502 Part 3 - Drawing 4x8 Fonts

15 Dec 2024

Introduction

Sticking with our ZX Spectrum video mode, we need a way to draw text onto the screen. Personally, I've always found the 8x8 fonts to not make good use of screen space. Therefore, we're going to draw a 4x8 font.

Requirements

A way of providing user input: mouse/clicking and text. A way of providing output: text.

The interface must be incredibly simple, such that it's easy to build applications with.

Text

The way that we will achieve having text is through a 4x8 font.

  • TODO - currently copied in @ to G in the fonts for testing, then next going to try and print it to the screen properly
    • not sure whether to have a text buffer which dictates where text is on the screen, this sounds good but it's probably going to take up a lot of memory
    • the other option is to have a text object list
    • I've managed to get the character drawing on the screen, however, it seems like the screen is now drawing onto odd lines, which is odd
  • ripping off something from the internet and using ChatGPT to transcribe the font
  • drawing a character
  • drawing text
    • pascal strings
  • draw byte
  • drawing numbers

LSB MSB rrrccccc 010aalll

addr_x = 000ccccc addr_y = 000aarrr

font

87654321 -> 00000087 65432000

Buttons

bitmap = $4000
attributes = $5800
last_attributes = $5B00
web3_status = $6000
web3_request = $6001
mouse_down = $3FFD
mouse_x = $3FFE
mouse_y = $3FFF

.macro STAI address
    LDX address
    STX $00
    LDX address + 1
    STX $01
    LDY #$00
    STA ($00),Y
.end

.macro TX2 address_1, address_2
    LDA address_1
    STA address_2
    LDA address_1 + 1
    STA address_2 + 1
.end

.macro CMP2 address_1, address_2
    LDA address_1
    CMP address_2
    BNE done
    LDA address_1 + 1
    CMP address_2 + 1
done:
    NOP
.end

.macro DEBUG address, pos
    LDA #%00100011
    STA attributes + pos
    LDA address
    STA bitmap + pos
    LDA address + 1
    STA bitmap + pos + 256
.end

init:
    JMP loop

mouse_record_x:
    .byte $00

mouse_record_y:
    .byte $00

update_mouse_record:
    LDA mouse_x
    STA mouse_record_x
    LDA mouse_y
    STA mouse_record_y
    RTS

mouse_attribute_offset:
    .word $0000

update_mouse_attribute_offset:
    LDA mouse_record_x
    AND #%11111000
    ROR
    ROR
    ROR
    STA mouse_attribute_offset
    LDA mouse_record_y
    AND #%00111000
    ASL
    ASL
    ORA mouse_attribute_offset
    STA mouse_attribute_offset
    LDA mouse_record_y
    AND #%11000000
    ROR
    ROR
    ROR
    ROR
    ROR
    ROR
    STA mouse_attribute_offset + 1
    RTS

attribute_address_offset:
    .word $0000

attribute_address_result:
    .word attributes

get_attribute_address_from_offset:
    CLC
    LDA #<attributes
    ADC attribute_address_offset
    STA attribute_address_result
    LDA #>attributes
    ADC attribute_address_offset + 1
    STA attribute_address_result + 1
    RTS

update_web3_request:
    LDA web3_status
    AND #%00000110
    BNE cancel_web3_connect
    LDA is_mouse_over_web3_square
    BNE try_web3_connect
    RTS

try_web3_connect:
    LDA web3_request
    ORA #%00000001
    STA web3_request
    RTS

cancel_web3_connect:
    LDA #$00
    STA web3_request
    RTS

is_mouse_over_web3_square:
    .byte $00

update_is_mouse_over_web3_square:
    CMP2 mouse_attribute_offset, web3_square_attribute_offset
    BNE set_is_mouse_over_web3_square_0
    LDA mouse_down
    BEQ set_is_mouse_over_web3_square_0
set_is_mouse_over_web3_square_1:
    LDA #$01
    STA is_mouse_over_web3_square
    RTS
set_is_mouse_over_web3_square_0:
    LDA #$00
    STA is_mouse_over_web3_square
    RTS

web3_square_attribute_offset:
    .word $001F

web3_square_state:
    .byte $00

update_web3_square_state:
    ;LDA is_mouse_over_web3_square
    LDA web3_status
    STA web3_square_state
    RTS

web3_square_attribute:
    .byte %00010000 ; no eth - red
    .byte %00110000 ; eth - yellow
    .byte %00000000
    .byte %01001000 ; connection requested - bright blue
    .byte %00000000
    .byte %01100000 ; connected - bright green

; Convert the attribute x, y to bitmap address, use XY registers
attr_xy_to_bitmap_address_result:
    .word bitmap
attr_xy_to_bitmap_address:
    ; column
    TXA
    AND #%00011111
    STA attr_xy_to_bitmap_address_result
    ; row
    TYA
    AND #%00000111
    ASL
    ASL
    ASL
    ASL
    ASL
    ORA attr_xy_to_bitmap_address_result
    STA attr_xy_to_bitmap_address_result
    ; area
    TYA
    AND #%00011000
    ROR
    ROR
    ROR
    ORA #>bitmap
    STA attr_xy_to_bitmap_address_result + 1
    RTS

; Convert the attribute x, y to an attribute address, use XY registers
attr_xy_to_attr_address_result:
    .word bitmap
attr_xy_to_attr_address:
    ; TODO
    RTS

font:
    .byte 0x06, 0x09, 0x0F, 0x09, 0x09, 0x0F, 0x06, 0x00
    .byte 0x60, 0xFA, 0x9E, 0xFE, 0xFE, 0x94, 0x64, 0x00
    .byte 0x44, 0x44, 0xEA, 0xEA, 0xE4, 0x44, 0x4E, 0x00
    .byte 0x40, 0x40, 0xE4, 0xEE, 0xEE, 0x44, 0xE0, 0x00
    .byte 0xF0, 0xF0, 0xB4, 0x1A, 0x1A, 0xB4, 0xF0, 0xF0
    .byte 0xFF, 0xFF, 0xBB, 0x55, 0x55, 0xBB, 0xFF, 0xFF
    .byte 0x07, 0x45, 0xA7, 0xA4, 0x44, 0xEC, 0x4C, 0x00
    .byte 0x74, 0x5D, 0x56, 0x5F, 0x56, 0xFB, 0xF2, 0x00
    .byte 0x81, 0xC3, 0xE7, 0xFF, 0xE7, 0xC3, 0x81, 0x00
    .byte 0x6A, 0xFA, 0x6A, 0x6A, 0x6A, 0xF0, 0x6A, 0x00
    .byte 0x77, 0xB8, 0xB6, 0x79, 0x39, 0x36, 0x31, 0x0E
    .byte 0x06, 0x0F, 0x06, 0x06, 0x06, 0xFF, 0xF6, 0x0F
    .byte 0x66, 0xF6, 0x66, 0x66, 0x66, 0x6F, 0x66, 0x00
    .byte 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x24, 0x00, 0x00
    .byte 0x00, 0x00, 0x06, 0x0F, 0x86, 0xF0, 0x00, 0x00
    .byte 0x00, 0x6F, 0x6F, 0x6F, 0xF6, 0xF6, 0xF6, 0x00
    .byte 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x00 ;  , !
    .byte 0xA0, 0xAA, 0xAE, 0x0A, 0x0E, 0x0A, 0x00, 0x00 ; ", #
    .byte 0x4A, 0xE2, 0x84, 0x44, 0x24, 0xE8, 0x4A, 0x00 ; $, %
    .byte 0x46, 0xA2, 0xA4, 0x40, 0x50, 0xA0, 0xE0, 0x30 ; &, '
    .byte 0x28, 0x44, 0x82, 0x82, 0x82, 0x44, 0x28, 0x00 ; (, )
    .byte 0x00, 0xA4, 0x44, 0xEE, 0x44, 0xA4, 0x00, 0x00 ; *, +
    .byte 0x00, 0x00, 0x00, 0x0E, 0x00, 0x60, 0x20, 0x40 ; ,, -
    .byte 0x02, 0x02, 0x04, 0x04, 0x04, 0x48, 0x48, 0x00 ; ., /
    .byte 0x44, 0xAC, 0xE4, 0xE4, 0xA4, 0xA4, 0x4E, 0x00 ; 0, 1
    .byte 0x44, 0xAA, 0x22, 0x44, 0x42, 0x8A, 0xE4, 0x00 ; 2, 3
    .byte 0x2E, 0xA8, 0xAC, 0xE2, 0x22, 0x2A, 0x24, 0x00 ; 4, 5
    .byte 0x4E, 0xA2, 0x82, 0xC4, 0xA4, 0xA8, 0x48, 0x00 ; 6, 7
    .byte 0x44, 0xAA, 0xAA, 0x46, 0xA2, 0xAA, 0x44, 0x00 ; 8, 9
    .byte 0x00, 0x44, 0x44, 0x00, 0x00, 0x44, 0x44, 0x08 ; :, ;
    .byte 0x10, 0x20, 0x4E, 0x80, 0x4E, 0x20, 0x10, 0x00 ; <, =
    .byte 0x84, 0x4A, 0x22, 0x14, 0x24, 0x40, 0x84, 0x00 ; >, ?
    .byte 0x44, 0xAA, 0xAA, 0xEE, 0xEA, 0x8A, 0x6A, 0x00 ; @, A
    .byte 0xC4, 0xAA, 0xA8, 0xC8, 0xA8, 0xAA, 0xC4, 0x00 ; B, C
    .byte 0xCE, 0xA8, 0xA8, 0xAC, 0xA8, 0xA8, 0xCE, 0x00 ; D, E
    .byte 0xE4, 0x8A, 0x88, 0xCE, 0x8A, 0x8A, 0x84, 0x00 ; F, G
    .byte 0xAE, 0xA4, 0xA4, 0xE4, 0xA4, 0xA4, 0xAE, 0x00 ; H, I
    .byte 0x2A, 0x2A, 0x2C, 0x2C, 0x2A, 0xAA, 0x4A, 0x00 ; J, K
    .byte 0x8A, 0x8E, 0x8E, 0x8E, 0x8A, 0x8A, 0xEA, 0x00 ; L, M
    .byte 0x2E, 0xAA, 0xEA, 0xEA, 0xEA, 0xAA, 0xAE, 0x00 ; N, O
    .byte 0xC4, 0xAA, 0xAA, 0xCA, 0x8A, 0x8A, 0x84, 0x02 ; P, Q
    .byte 0xC4, 0xAA, 0xA8, 0xC4, 0xA2, 0xAA, 0xA4, 0x00 ; R, S
    .byte 0xEA, 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4E, 0x00 ; T, U
    .byte 0xAA, 0xAA, 0xAA, 0xAA, 0xAE, 0x4E, 0x4A, 0x00 ; V, W
    .byte 0xAA, 0xAA, 0xEA, 0x44, 0xE4, 0xA4, 0xA4, 0x00 ; X, Y
    .byte 0xE6, 0x24, 0x44, 0x44, 0x44, 0x84, 0xE6, 0x00 ; Z, [
    .byte 0x06, 0x82, 0x82, 0x42, 0x42, 0x22, 0x26, 0x00 ; \, ]
    .byte 0x00, 0x40, 0xE0, 0xA0, 0x00, 0x00, 0x00, 0x0F ; ^, _
    .byte 0x60, 0x40, 0x2C, 0x02, 0x06, 0x0A, 0x06, 0x00 ; `, a
    .byte 0x80, 0x80, 0xC4, 0xAA, 0xA8, 0xAA, 0xC4, 0x00 ; b, c
    .byte 0x20, 0x20, 0x64, 0xAA, 0xAE, 0xA8, 0x66, 0x00 ; d, e
    .byte 0x20, 0x40, 0x46, 0xEA, 0x4A, 0x46, 0x42, 0x0C ; f, g
    .byte 0x84, 0x80, 0xCC, 0xA4, 0xA4, 0xA4, 0xA4, 0x00 ; h, i
    .byte 0x28, 0x08, 0x2A, 0x2A, 0x2C, 0x2A, 0xAA, 0x40 ; j, k
    .byte 0xC0, 0x40, 0x4A, 0x4E, 0x4E, 0x4A, 0xEA, 0x00 ; l, m
    .byte 0x00, 0x00, 0xC4, 0xAA, 0xAA, 0xAA, 0xA4, 0x00 ; n, o
    .byte 0x00, 0x00, 0xC6, 0xAA, 0xAA, 0xC6, 0x82, 0x83 ; p, q
    .byte 0x00, 0x00, 0xC6, 0xA8, 0x84, 0x82, 0x8C, 0x00 ; r, s
    .byte 0x00, 0x40, 0xEA, 0x4A, 0x4A, 0x4A, 0x26, 0x00 ; t, u
    .byte 0x00, 0x00, 0xAA, 0xAA, 0xAE, 0x4E, 0x4A, 0x00 ; v, w
    .byte 0x00, 0x00, 0xAA, 0xAA, 0x4A, 0xA6, 0xA2, 0x0C ; x, y
    .byte 0x02, 0x04, 0xE4, 0x28, 0x44, 0x84, 0xE2, 0x00 ; z, {
    .byte 0x48, 0x44, 0x44, 0x02, 0x44, 0x44, 0x48, 0x00 ; |, }
    .byte 0x50, 0xA0, 0x04, 0x04, 0x0A, 0x0A, 0x0E, 0x00
    .byte 0x4A, 0xA0, 0x8A, 0x8A, 0x8A, 0xAA, 0x46, 0x20
    .byte 0x24, 0x4A, 0x4C, 0xA2, 0xE6, 0x8A, 0x66, 0x00
    .byte 0xA8, 0x04, 0xCC, 0x22, 0x66, 0xAA, 0x66, 0x00
    .byte 0xE0, 0xE0, 0xC6, 0x28, 0x68, 0xA6, 0x64, 0x0C
    .byte 0x4A, 0xA0, 0x44, 0xAA, 0xEE, 0x88, 0x66, 0x00
    .byte 0x8A, 0x40, 0x40, 0xAC, 0xE4, 0x84, 0x64, 0x00
    .byte 0x48, 0xA4, 0x00, 0xCC, 0x44, 0x44, 0x44, 0x00
    .byte 0xAE, 0x44, 0xAA, 0xAA, 0xEE, 0xAA, 0xAA, 0x00
    .byte 0x20, 0x48, 0xE6, 0x86, 0xCC, 0x8C, 0xE2, 0x00
    .byte 0x74, 0xAA, 0xA4, 0xFA, 0xAA, 0xAA, 0xB4, 0x00
    .byte 0xA8, 0x04, 0x44, 0xAA, 0xAA, 0xAA, 0x44, 0x00
    .byte 0x48, 0xA4, 0x00, 0xAA, 0xAA, 0xAA, 0x66, 0x00
    .byte 0xAA, 0x04, 0xAA, 0xAA, 0xAA, 0x6A, 0x24, 0xC0
    .byte 0xA4, 0x04, 0xAA, 0xA8, 0xA8, 0xAA, 0x44, 0x04
    .byte 0x4A, 0xAA, 0x84, 0xCE, 0x84, 0x8E, 0xE4, 0x00
    .byte 0xC2, 0xA5, 0xC4, 0xAE, 0xF4, 0xA4, 0x98, 0x00
    .byte 0x22, 0x44, 0xC0, 0x2C, 0x64, 0xA4, 0x64, 0x00
    .byte 0x22, 0x44, 0x00, 0x4A, 0xAA, 0xAA, 0x46, 0x00 ; ¢, £
    .byte 0x5E, 0xA0, 0x02, 0xCA, 0xAE, 0xAE, 0xAA, 0x00 ; ¤, ¥
    .byte 0x64, 0xAA, 0xAA, 0x64, 0x00, 0xEE, 0x00, 0x00 ; ¦, §
    .byte 0x40, 0x00, 0x40, 0x40, 0x87, 0xA4, 0x40, 0x00 ; ¨, ©
    .byte 0x04, 0x04, 0x0E, 0x0C, 0xE2, 0x24, 0x0E, 0x00 ; ª, «
    .byte 0x44, 0x40, 0xE4, 0x24, 0xA4, 0xE4, 0x24, 0x00
    .byte 0x00, 0x5A, 0x5A, 0xA5, 0x5A, 0x5A, 0x00, 0x00 ; ®, ¯
    .byte 0x8A, 0x25, 0x8A, 0x25, 0x8A, 0x25, 0x8A, 0x25 ; °, ±
    .byte 0xD4, 0x74, 0xD4, 0x74, 0xD4, 0x74, 0xD4, 0x74 ; ², ³
    .byte 0x44, 0x44, 0x4C, 0xC4, 0x4C, 0x44, 0x44, 0x44 ; ´, µ
    .byte 0xA0, 0xA0, 0xA0, 0xAE, 0xAA, 0xAA, 0xAA, 0xAA ; ¶, ·
    .byte 0x0A, 0x0A, 0xCA, 0x42, 0xCA, 0x4A, 0x4A, 0x4A ; ¸, ¹
    .byte 0xA0, 0xA0, 0xAE, 0xA2, 0xAA, 0xAA, 0xAA, 0xAA ; º, »
    .byte 0xAA, 0xAA, 0xAA, 0x2E, 0xE0, 0x00, 0x00, 0x00 ; ¼, ½
    .byte 0x40, 0x40, 0xC0, 0x4C, 0xC4, 0x04, 0x04, 0x04 ; ¾, ¿
    .byte 0x44, 0x44, 0x44, 0x7F, 0x00, 0x00, 0x00, 0x00 ; À, Á
    .byte 0x04, 0x04, 0x04, 0xF7, 0x44, 0x44, 0x44, 0x44 ; Â, Ã
    .byte 0x04, 0x04, 0x04, 0xFF, 0x04, 0x04, 0x04, 0x04 ; Ä, Å
    .byte 0x4A, 0x4A, 0x7A, 0x4B, 0x7A, 0x4A, 0x4A, 0x4A ; Æ, Ç
    .byte 0xA0, 0xA0, 0xBF, 0x88, 0xFB, 0x0A, 0x0A, 0x0A ; È, É
    .byte 0xA0, 0xA0, 0xBF, 0x00, 0xFB, 0x0A, 0x0A, 0x0A ; Ê, Ë
    .byte 0xA0, 0xA0, 0xBF, 0x80, 0xBF, 0xA0, 0xA0, 0xA0 ; Ì, Í
    .byte 0xA4, 0xA4, 0xBF, 0x00, 0xBF, 0xA0, 0xA0, 0xA0 ; Î, Ï
    .byte 0xA0, 0xA0, 0xAF, 0xF0, 0x0F, 0x04, 0x04, 0x04 ; Ð, Ñ
    .byte 0x0A, 0x0A, 0x0A, 0xFF, 0xA0, 0xA0, 0xA0, 0xA0 ; Ò, Ó
    .byte 0x40, 0x40, 0x77, 0x44, 0x77, 0x04, 0x04, 0x04 ; Ô, Õ
    .byte 0x0A, 0x0A, 0x0A, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA ; Ö, ×
    .byte 0x44, 0x44, 0xF4, 0x4C, 0xF0, 0x40, 0x40, 0x40 ; Ø, Ù
    .byte 0x0F, 0x0F, 0x0F, 0x7F, 0x4F, 0x4F, 0x4F, 0x4F ; Ú, Û
    .byte 0x0C, 0x0C, 0x0C, 0x0C, 0xFC, 0xFC, 0xFC, 0xFC ; Ü, Ý
    .byte 0x3F, 0x3F, 0x3F, 0x3F, 0x30, 0x30, 0x30, 0x30 ; Þ, ß
    .byte 0x04, 0x0A, 0x0C, 0x5A, 0xAA, 0xAC, 0x58, 0x08 ; à, á
    .byte 0x00, 0xEF, 0xAA, 0x8A, 0x8A, 0x8A, 0x8A, 0x00 ; â, ã
    .byte 0xF0, 0x90, 0x47, 0x2A, 0x4A, 0x9A, 0xF4, 0x00 ; ä, å
    .byte 0x00, 0x55, 0x5A, 0x52, 0x52, 0x62, 0x42, 0x80 ; æ, ç
    .byte 0xE6, 0x49, 0xA9, 0xAF, 0xA9, 0x49, 0xE6, 0x00 ; è, é
    .byte 0x00, 0x63, 0x94, 0x92, 0x96, 0x69, 0xF6, 0x00 ; ê, ë
    .byte 0x02, 0x06, 0x6A, 0x9E, 0xFA, 0x9C, 0x68, 0x00 ; ì, í
    .byte 0x00, 0x64, 0x8A, 0xEA, 0x8A, 0x6A, 0x0A, 0x00 ; î, ï
    .byte 0x04, 0xE4, 0x0E, 0xE4, 0x04, 0xE0, 0x0E, 0x00 ; ð, ñ
    .byte 0x82, 0x44, 0x28, 0x44, 0x82, 0x00, 0xEE, 0x00 ; ò, ó
    .byte 0x04, 0x24, 0x54, 0x44, 0x44, 0x44, 0x48, 0x40 ; ô, õ
    .byte 0x00, 0x45, 0x0A, 0xE0, 0x05, 0x4A, 0x00, 0x00 ; ö, ÷
    .byte 0x40, 0xA0, 0xA0, 0x44, 0x00, 0x00, 0x00, 0x00 ; ø, ù
    .byte 0x03, 0x02, 0x02, 0x62, 0x0A, 0x06, 0x04, 0x00 ; ú, û
    .byte 0xCC, 0xA2, 0xA4, 0xAE, 0x00, 0x00, 0x00, 0x00 ; ü, ý
    .byte 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00 ; þ, ÿ

draw_text_ptr:
    .byte $00, $00
draw_text_x:
    .byte $00
draw_text_y:
    .byte $00
draw_text_attribute_colour:
    .byte $00

draw_text_cursor:
    .byte $00
draw_text:
    LDA #$00
    STA draw_text_cursor
    LDA draw_text_ptr
    STA $00
    LDA draw_text_ptr + 1
    STA $01
draw_text_loop:
    LDY draw_text_cursor
    INY
    LDA ($00),Y
    STA draw_char_char

    LDA draw_text_x
    CLC
    ADC draw_text_cursor
    STA draw_char_x
    LDA draw_text_y
    STA draw_char_y
    JSR draw_char

    INC draw_text_cursor
    LDY #$00
    LDA draw_text_cursor
    CMP ($00),Y
    BNE draw_text_loop

    RTS

; uses draw_char_x and draw_char_y
draw_byte_byte:
    .byte $00
draw_byte:
    LDA draw_byte_byte
    AND #$F0
    CLC
    ROR
    ROR
    ROR
    ROR
    JSR draw_nibble
    LDX draw_char_x
    INX
    STX draw_char_x
    LDA draw_byte_byte
    AND #$0F
    JSR draw_nibble
    RTS
; uses accumulator as parameter
draw_nibble:
    ; compare with 10
    CMP #$0A
    BCS draw_nibble_a_f
    ; to convert to ascii
    CLC
    ADC #$30
    STA draw_char_char
    JSR draw_char
    RTS
draw_nibble_a_f:
    ; to convert to ascii
    CLC
    ADC #$37
    STA draw_char_char
    JSR draw_char
    RTS

draw_char_char:
    .text "C"
draw_char_x:
    .byte $00
draw_char_y:
    .byte $00

draw_char_bitmap:
    .word bitmap
draw_char_font:
    .word font
set_draw_char_font:
    CLC
    LDA draw_char_char
    ; Rotate right to remove last significant bit
    AND #%00111110
    ASL
    ASL
    TAX

    LDA draw_char_char
    AND #%11000000
    ROL
    ROL
    ROL
    CLC
    TAY

    TXA
    ADC #<font
    STA draw_char_font
    TYA
    ADC #>font
    STA draw_char_font + 1
    RTS
set_draw_char_bitmap:
    LDA draw_char_x
    ROR
    TAX
    LDY draw_char_y
    JSR attr_xy_to_bitmap_address
    TX2 attr_xy_to_bitmap_address_result, draw_char_bitmap
    RTS
draw_char:
    JSR set_draw_char_bitmap
    JSR set_draw_char_font
    LDA draw_char_bitmap
    STA $02
    LDA draw_char_bitmap + 1
    STA $03
    LDA draw_char_font
    STA $04
    LDA draw_char_font + 1
    STA $05
    ; set the counter to 0
    LDY #$00
draw_char_line:
    ; Load the byte line to draw
    LDA ($04),Y
    TAX
draw_char_line_choose_nibble:
    ; Shift byte line left if far bit of ascii is 0
    LDA draw_char_char
    AND #$01
    BEQ draw_char_line_shift_right
    TXA
    ASL
    ASL
    ASL
    ASL
    CLC
    TAX
draw_char_line_shift_right:
    TXA
    AND #$F0
    TAX
    ; Shift byte line right if x position is even
    LDA draw_char_x
    AND #$01
    BEQ draw_char_line_keep_left
    TXA
    ROR
    ROR
    ROR
    ROR
    STA $06
    LDX #$00
    LDA ($02,X)
    AND #$F0
    ORA $06
    TAX
    JMP draw_char_line_final
draw_char_line_keep_left:
    STX $06
    LDX #$00
    LDA ($02,X)
    AND #$0F
    ORA $06
    TAX
draw_char_line_final:
    TXA
    LDX #$00
    STA ($02,X)
    ; Increment significant bit of address
    INC $03
    ; Increment counter
    INY
    ; Check to see whether counter has written all 8 lines
    CPY #$08
    BNE draw_char_line
    RTS

draw_web3_square:
    TX2 web3_square_attribute_offset, attribute_address_offset
    JSR get_attribute_address_from_offset
    LDX web3_square_state
    LDA web3_square_attribute,X
    STAI attribute_address_result
    RTS

draw_mouse_square:
    LDA is_mouse_over_web3_square
    BEQ draw_mouse_square_force
    RTS
draw_mouse_square_force:
    TX2 mouse_attribute_offset, attribute_address_offset
    JSR get_attribute_address_from_offset
    JSR get_mouse_colour
    STAI attribute_address_result
    RTS
get_mouse_colour:
    LDA mouse_down
    BNE return_mouse_down_colour
return_mouse_up_colour:
    LDA #%00110000
    RTS
return_mouse_down_colour:
    LDA #%01010000
    RTS

babba:
    .pstr "This is my new favourite console!"

loop:
    JSR update_mouse_record
    JSR update_mouse_attribute_offset
    JSR update_is_mouse_over_web3_square
    JSR update_web3_request
    JSR update_web3_square_state

    LDA #$03
    STA draw_text_x
    LDA #$03
    STA draw_text_y
    LDA #<babba
    STA draw_text_ptr
    LDA #>babba
    STA draw_text_ptr + 1
    JSR draw_text

    LDA #$00
    STA draw_char_x
    LDA #$00
    STA draw_char_y
    LDA mouse_x
    STA draw_byte_byte
    JSR draw_byte

    LDX draw_char_x
    INX
    STX draw_char_x
    LDA mouse_y
    STA draw_byte_byte
    JSR draw_byte

    JSR draw_mouse_square
    JSR draw_web3_square
    JMP loop