# =============================================================================================================
# *
# * Copyright (c) Mike
# *
# * File Name: vgaTestCode.asm
# *
# * Version: V1.0
# *
# * Release Date:
# *
# * Author(s): M.Freeman
# *
# * Description: space invaders test code
# *
# * Conditions of Use: THIS CODE IS COPYRIGHT AND IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND, INCLUDING,
# *                    BUT NOT LIMITED TO, ANY IMPLIED WARRANTY OF MERCHANTABILITY AND FITNESS FOR A
# *                    PARTICULAR PURPOSE.
# *
# * Notes:
# *
# =============================================================================================================


start: 
    run( init_lcd )
    run( init_game )

    clear_screen( 0 )

    run( draw_bob_screen )

 	call delayLong
 	call delayLong
 	call delayLong
 	call delayLong
 	call delayLong
 	call delayLong
 	call delayLong
 	call delayLong

    clear_screen( 0 )

 	call delayLong

    run( draw_game_screen )

repeat:
 	call delaylong
	draw_box( BLACK, 24, 24, 132, 106 )	

 	call delaylong
    run( draw_game_grid )
    run( init_grid )
 	call delaylong

loop:
    move RA 1
    store RA player

    run( make_move_x )
    run( check_win_condition )
    run( check_draw_condition )
 	call delaylong

    load RA finish
    and RA 0xFF
    jumpnz repeat

    load RA win
    and RA 0xFF
    jumpnz repeat

    load RA restart
    and RA 0xFF
    jumpnz start

    move RA 0
    store RA player

    run( make_move_o )
    run( check_win_condition )
    run( check_draw_condition )
 	call delaylong

    load RA finish
    and RA 0xFF
    jumpnz repeat

    load RA win
    and RA 0xFF
    jumpnz repeat

    load RA restart
    and RA 0xFF
    jumpnz start

    jump loop

#######################
# GENERAL SUBROUTINES #
#######################
#<<
# ------------------ 
# - Software Delay -
# ------------------

delay:
    move RB 0x0F
    jump delay_start

delayVeryShort:
    move RB 0x1F 
    jump delay_start

delayShort:
    move RB 0x3F 
    jump delay_start

delayMedium:
    move RB 0x7F 
    jump delay_start

delayLong:
    move RB 0xFF 
    and RB 0xFF
    jump delay_start

delayLonger:
    moved( RB, 0x01FF ) 
    jump delay_start

delayVeryLong:
    move RB 0xFF 

delay_start:
    movea( RA, 0xFFF )

delay_loop:
    sub RA 1
    jumpnz delay_loop
    sub RB 1
    jumpnz delay_start

    ret

# -------------
# - BIN 2 DEC -
# -------------

bin_2_dec:
	move RB RA

	move RA 0
	store RA bin_2_dec_1s_cnt
	store RA bin_2_dec_10s_cnt
	store RA bin_2_dec_100s_cnt

100s_loop:
	sub RB	100
	move RC RB
	rol RC
    and RC 1
	jumpnz 100s_loop_exit
	load RA bin_2_dec_100s_cnt
	add RA 1
	store RA bin_2_dec_100s_cnt
	jump 100s_loop

100s_loop_exit:
	add RB 100

10s_loop:
	sub RB	10
	move RC RB
	rol RC
    and RC 1
	jumpnz 10s_loop_exit
	load RA bin_2_dec_10s_cnt
	add RA 1
	store RA bin_2_dec_10s_cnt
	jump 10s_loop

10s_loop_exit:
	add RB 10

	move RA RB
	store RA bin_2_dec_1s_cnt
	ret


####################
# TILE SUBROUTINES #
####################
#<<
# -------------
# - DRAW TILE -
# -------------

draw_tile_subroutine:
#   cpu_colour_reg
    load RA block_colour
    store RA CPU_COLOUR_REG         # colour

#   xy_position:
    load RA block_x_top_pos         # x
    store RA TILE_X_REG
    load RA block_y_top_pos         # y
    store RA TILE_Y_REG

#   set tile address
    move RA RD
    store RA CPU_SRC_ADDR_REG       # tile addr in video memory  

#   ctl reg
    move RA DRAW_TILE
    store RA CPU_CTL_REG            # start 

draw_tile_wait:
    movea( RA, CPU_STATUS_REG )
    load RB (RA)
    and RB CTL_MASK
    jumpz draw_tile_wait
    ret

# ----------------
# - OVERLAY TILE -
# ----------------

overlay_tile_subroutine:
#   cpu_colour_reg
    load RA block_colour
    store RA CPU_COLOUR_REG         # colour

#   xy_position:
    load RA block_x_top_pos         # x
    store RA TILE_X_REG
    load RA block_y_top_pos         # y
    store RA TILE_Y_REG

#   set tile address
    move RA RD
    store RA CPU_SRC_ADDR_REG       # tile addr in video memory  

#   ctl reg
    move RA OVERLAY_TILE
    store RA CPU_CTL_REG            # start 

overlay_tile_wait:
    movea( RA, CPU_STATUS_REG )
    load RB (RA)
    and RB CTL_MASK
    jumpz overlay_tile_wait
    ret

# -------------------
# - DRAW TILE DIGIT -
# -------------------

# draw digit character at XY position, tile selected by NIBBLE
# colour              : block_colour
# X pos               : block_x_top_pos
# Y pos               : block_y_top_pos 
# offset              : nibble 

draw_tile_digit:
    moved( RD, zero_CHAR )            # base address
    load RA nibble                    # get offset
    and RA 0x0F
    move RB RA
    sub RB 9                          # <= 9 
    jumpc draw_tile_digit_exit

    asl RA                            # x 4
    asl RA
    add RD RA                         # add offset to base address
    
    call draw_tile_subroutine

draw_tile_digit_exit:
    ret

# -------------------
# - DRAW TILE ASCII -
# -------------------

# draw ASCII character at XY position, tile selected by BYTE (0x20 - 0x7F)
# colour              : block_colour
# X pos               : block_x_top_pos
# Y pos               : block_y_top_pos 
# offset              : byte 

draw_tile_ascii:
    moved( RD, sp_CHAR )        # base address SPACE (0x20)
    load RA byte                # get ASCII value
    and RA 0xFF     
    move RB RA 
    sub RB 0x7F                 # <= 0x7F
    jumpc draw_tile_digit_exit

    asl RA                      # x 4
    asl RA
    add RD RA                   # add offset to base address
    
    call draw_tile_subroutine

    ret

# ------------------
# - DRAW TILE CHAR -
# ------------------

# draw CHAR character at XY position, tile selected by WORD address
# colour              : block_colour
# X pos               : block_x_top_pos
# Y pos               : block_y_top_pos 
# address             : word

draw_tile_char:
    load RA word                # get ASCII value
    move RD RA                   
    
    call draw_tile_subroutine

    ret
#>>

#####################
# BLOCK SUBROUTINES #
#####################
#<<
# ---------------
# - BLOCK WRITE -
# ---------------

# write data directly to frame buffer
# colour        : block_colour
# start address : block_start_address
# end address   : block_start_address + block_size
#

block_write_subroutine:
#   cpu_colour_reg
    movea( RB, CPU_COLOUR_REG )
    load RA block_colour
    store RA (RB)

#   cpu_data_in_reg - end src addr
    movea( RB, CPU_DATA_IN_REG )
    load RA block_start_address
    addm RA block_width
    store RA (RB)

#   cpu_addr_reg
    movea( RB, CPU_DST_ADDR_REG )
    load RA block_start_address
    store RA (RB)

#   ctl reg 
    movea( RA, CPU_CTL_REG )
    move RB BLOCK_WRITE
    store RB (RA)

block_write_wait:
    movea( RA, CPU_STATUS_REG )
    load RB (RA)
    and RB CTL_MASK
    jumpz block_write_wait
    ret

# ------------
# - DRAW BOX -
# ------------

#             1   2  3  4  5 
#  draw_box( RED, 6, 2, 7, 3 )
#             |   |  |  |  |
# 1 : COLOUR --   |  |  |  |
# 2 : X_TOP -------  |  |  |
# 3 : Y_TOP ----------  |  |
# 4 : X_BOTTOM ----------  |
# 5 : Y_BOTTOM -------------

# draw box directly to frame buffer, multiples of 2 pixel along X axis
# 
# colour                       : block_colour
# start addr in frame buffer   : block_start_address
# number of 2 pixel blocks     : block_width
# number of rows               : block_depth


draw_box_subroutine:
    call block_write_subroutine

    load RA block_depth
    sub RA 1
    store RA block_depth
    jumpz draw_box_exit

    load RA block_start_address
    add RA eval( VDC_MAX_X_LIMIT >> 1 )
    store RA block_start_address

    jump draw_box_subroutine

draw_box_exit:
    ret

# ------------------
# - DRAW RECTANGLE -
# ------------------

# draw rectangle directly to frame buffer, multiples of 2 pixel along X axis

# colour                  : block_colour
# top left x location     : block_x_top_pos
# bottom right x location : block_x_bottom_pos
# top left y location     : block_y_top_pos
# bottom right y location : block_y_bottom_pos

draw_rectangle:
#   calc start address
    load RA block_x_top_pos
    store RA TILE_X_REG
    load RA block_y_top_pos
    store RA TILE_Y_REG
    load RA TILE_POS
	store RA block_start_address

#   calc width
    load RA block_x_bottom_pos 
    subm RA block_x_top_pos
    asr RA
    store RA block_width

#   draw line
    call block_write_subroutine

#   check if all rows drawn
    load RA block_y_bottom_pos
    subm RA block_y_top_pos
    jumpz draw_rectangle_exit

#   increment Y
    load RA block_y_top_pos
    add RA 1
    store RA block_y_top_pos
    jump draw_rectangle

draw_rectangle_exit:
    ret

# --------------
# - BLOCK COPY -
# --------------

# write data directly to frame buffer
# colour              : block_colour
# start address       : block_start_address
# end address         : block_start_address + block_width
# destination address : block_destination_address 
#

block_copy_subroutine:
#   cpu_data_in_reg - end src addr
    movea( RB, CPU_DATA_IN_REG )
    load RA block_start_address
    addm RA block_width
    store RA (RB)

#   cpu_addr_reg
    movea( RB, CPU_SRC_ADDR_REG )
    load RA block_start_address
    store RA (RB)

#   cpu_dest_reg
    movea( RB, CPU_DST_ADDR_REG )
    load RA block_destination_address
    store RA (RB)

#   ctl reg 
    movea( RA, CPU_CTL_REG )
    move RB BLOCK_COPY
    store RB (RA)

block_copy_wait:
    movea( RA, CPU_STATUS_REG )
    load RB (RA)
    and RB CTL_MASK
    jumpz block_copy_wait
    ret
    ret

# ------------
# - COPY BOX -
# ------------

#                1  2  3  4  5  6
#      copy_box( 0  0  5  5  6  6 )
#                |  |  |  |  |  | 
# 1 : SRC_X_TOP --  |  |  |  |  |
# 2 : SRC_Y_TOP -----  |  |  |  |
# 3 : SRC_X_BOTTOM -----  |  |  |
# 4 : SRC_Y_BOTTOM --------  |  |
# 5 : DEST_X_TOP -------------  |
# 6 : DEST_Y_TOP ----------------

# draw box directly to frame buffer, multiples of 2 pixel along X axis
# 
# colour                       : block_colour
# start addr in frame buffer   : block_start_address
# destination address          : block_destination_address 
# number of 2 pixel blocks     : block_width
# number of rows               : block_depth

copy_box_subroutine:
    call block_copy_subroutine

    load RA block_depth
    sub RA 1
    store RA block_depth
    jumpz copy_box_exit

    load RA block_start_address
    add RA eval( VDC_MAX_X_LIMIT >> 1 )
    store RA block_start_address

    load RA block_destination_address
    add RA eval( VDC_MAX_X_LIMIT >> 1 )
    store RA block_destination_address

    jump copy_box_subroutine

copy_box_exit:
    ret

#>>

###########################
# SERIAL PORT SUBROUTINES #
###########################
#<<
# ------------------------------------------
# - Copy string (must terminate with a \0) -
# ------------------------------------------
# Source / destination addresses passed in SRCADDR / DESTADDR

strcpy:
    load RA srcAddr          # get source address
    move RB RA
    load RA destAddr         # get destination address
    move RC RA 

strcpy_loop:              
    load RA (RB)             # load  char
    and RA 0xFF
    jumpz strcpy_exit        # exit if 0
    store RA (RC)            # copy
    add RB 1
    add RC 1
    jump strcpy_loop         # repeat

strcpy_exit:
    ret

# ----------------------------------------
# - TX String (must terminate with a \0) -
# ----------------------------------------
# data in txBuffer written to serial port, blocking 

txString:
    movea( RB, txBuffer )  # get string address

tx_loop:              
    load RA (RB)             # load  char
    and RA 0xFF
    jumpz tx_exit            # exit if 0
    store RA UART_TX         # tx

waitTX:
    load RA UART_STATUS      # test TX status wait till 1
    and RA 0x04          
    jumpz waitTX    

    add RB 1                 # inc address
    jump tx_loop             # repeat

tx_exit:
    move RA 0
    store RA txBufferIndex
    ret

# --------------------------------
# - Add NULL to tx string buffer -
# --------------------------------

addNULL:
    load RA txBufferIndex 
    movea( RC, txBuffer )
    add RC RA 
    move RA 0
    store RA (RC)
    ret

# ---------------------------------
# - Add LF CR to tx string buffer -
# ---------------------------------

addLFCR:
    load RA txBufferIndex 
    movea( RC, txBuffer )
    add RC RA 
    add RA 2
    store RA txBufferIndex

    move RA 0x0A
    store RA (RC)
    add RC 1
    move RA 0x0D
    store RA (RC)
    ret

# ---------------------------------
# - Add SPACE to tx string buffer -
# ---------------------------------

addSPACE:
    load RA txBufferIndex 
    movea( RC, txBuffer )
    add RC RA 
    add RA 1
    store RA txBufferIndex

    move RA 0x20
    store RA (RC)
    ret

# --------------------------------------------
# - Convert word into hexidecimal characters -
# --------------------------------------------
# data to be convert in variable "word", characters written to txBuffer

word2Hex:
    load RA word
    asr RA
    asr RA
    asr RA
    asr RA
    asr RA
    asr RA
    asr RA
    asr RA
    store RA byte
    call byte2Hex

    load RA word
    and RA 0xFF
    store RA byte
    call byte2Hex

    ret

# --------------------------------------------
# - Convert byte into hexidecimal characters -
# --------------------------------------------
# data to be convert in variable "byte", characters written to txBuffer

byte2Hex:
    load RA txBufferIndex 
    movea( RC, txBuffer )
    add RC RA
    add RA 2
    store RA txBufferIndex

    movea( RB, nibble2HexTable )
    load RA byte
    and RA 0xF0
    asr RA
    asr RA
    asr RA
    asr RA
    add RB RA

    load RA (RB)
    store RA (RC)
    add RC 1

    movea( RB, nibble2HexTable )

    load RA byte
    and RA 0x0F
    add RB RA

    load RA (RB)
    store RA (RC)

    ret

# ----------------------------------------
# - Convert byte into decimal characters -
# ----------------------------------------
# data to be convert in variable "byte", characters written to txBuffer

byte2Dec:
    load RA txBufferIndex 
    movea( RC, txBuffer )
    add RC RA
    add RA 3
    store RA txBufferIndex

    load RA byte
    and RA 0xFF
    move RB 0

byte2Dec_100s_loop:
    sub RA 100                   # sub 100
    jumpc byte2Dec_100s_exit     # yes, exit
    add RB 1                     # inc count 
    jump byte2Dec_100s_loop      # repeat

byte2Dec_100s_exit:
    add RB 0x30
    store RB (RC)
    add RC 1
    
    add RA 100                   # undo last sub
    move RB 0
 
byte2Dec_10s_loop:
    sub RA 10                    # sub 10
    jumpc byte2Dec_10s_exit      # yes, exit
    add RB 1                     # inc count 
    jump byte2Dec_10s_loop       # repeat

byte2Dec_10s_exit:
    add RB 0x30
    store RB (RC)
    add RC 1
    
    add RA 10                    # undo last sub
    add RA 0x30
    store RA (RC)

    ret

# --------------
# - RX TX Test -
# --------------

rx_tx_test:
    load RA UART_STATUS      # has ASCII char been RX?
    and RA 0x01
    jumpz rx_tx_test         # no check again

    load RA UART_RX
    store RA UART_TX

rx_tx_waitTX:
    load RA UART_STATUS      # test TX status wait till 1
    and RA 0x04          
    jumpz rx_tx_waitTX    

    jump rx_tx_test          # repeat

# ------------------
# - Welcome banner -
# ------------------

welcome_banner:
    move RA 0
    store RA txBufferIndex 

    movea( RA, welcome )           # set string address      
    store RA srcAddr         
    movea( RA, txBuffer )          # set buffer address
    store RA destAddr
    call strcpy 
    call txString
    ret
#>>

###########################
# LCD DISPLAY SUBROUTINES #
###########################
#<<
# ---------------
# - LCD PULSE E -
# ---------------

# GPIO PORT
# ---------
# 128  bit 7 : NU
# 64   bit 6 : RW (0)
# 32   bit 5 : E
# 16   bit 4 : RS (1=text, 0=config)
# 8    bit 3 : D7
# 4    bit 2 : D6
# 2    bit 1 : D5
# 1    bit 0 : D5

lcd_pulse_e:
    load RA GPIO_A_DATA       # set enable line
    add RA 32
    store RA GPIO_A_OUT
    
    call lcd_delay

    load RA GPIO_A_DATA       # clear enable line
    sub RA 32
    store RA GPIO_A_OUT

    call lcd_delay
    ret

# ------------------
# - LCD SET LINE 1 -
# ------------------
# LCD_LINE_1 = 0x80 LCD RAM address for the 1st line

lcd_line_1:
    move RA 0x08
    store RA GPIO_A_OUT
    call lcd_delay

    call lcd_pulse_e

    move RA 0x00
    store RA GPIO_A_OUT
    call lcd_delay

    call lcd_pulse_e
    ret

# ------------------
# - LCD SET LINE 2 -
# ------------------
# LCD_LINE_2 = 0xC0 LCD RAM address for the 2nd line

lcd_line_2:
    move RA 0x0C
    store RA GPIO_A_OUT
    call lcd_delay

    call lcd_pulse_e

    move RA 0x00
    store RA GPIO_A_OUT
    call lcd_delay

    call lcd_pulse_e
    ret

# -----------------
# - LCD TX STRING -
# -----------------

lcd_tx:
    move RA 0                 # clear all bits
    store RA GPIO_A_OUT

    load RA lcd_config
    and RA 0xFF
    jumpnz lcd_tx_continue

    load RA GPIO_A_DATA       # set RS bit (text)
    add RA 16
    store RA GPIO_A_OUT

lcd_tx_continue:
    load RA lcd_pntr
    move RB RA

    load RA (RB)              # exit if NULL
    and RA 0xFF
    jumpz lcd_tx_exit

    and RA 0xF0               # extract high nibble
    ror RA
    ror RA
    ror RA
    ror RA
    addm RA GPIO_A_DATA
    store RA GPIO_A_OUT
    call lcd_delay

    call lcd_pulse_e
 
    load RA (RB)
    and RA 0x0F              # extract low nibble
    move RB RA
    load RA GPIO_A_DATA
    and RA 0xF0
    add RA RB
    store RA GPIO_A_OUT
    call lcd_delay

    call lcd_pulse_e

    move RA 0
    store RA GPIO_A_OUT

    call lcd_delay

    load RA lcd_pntr
    add RA 1
    store RA lcd_pntr
    jump lcd_tx

lcd_tx_exit:
    ret

# ------------------
# - LCD TIME DELAY -
# ------------------

lcd_delay:
    moved( RA, 0x200 )
    store RA lcd_delay_count

lcd_delay_loop:
    load RA lcd_delay_count
    sub RA 1
    store RA lcd_delay_count
    jumpnz lcd_delay_loop

    ret

#>>

##########################
# CONTROLLER SUBROUTINES #
##########################
#<<
# ----------------------
# - READ ROTARY SWITCH -
# ----------------------   
  
# 0=STOP, 1=LEFT, 2=RIGHT

read_rotary_switch:
	move RB 0
	
	load RA ROTARY_DATA        # move?
	and RA 0x04	
	jumpz read_rotary_switch_exit
	
	store RA ROTARY_RESET	   # reset flag
	
	load RA ROTARY_DATA        # left/right
	and RA 0x02	
	jumpz read_rotary_switch_left
	
read_rotary_switch_right:
	move RB 1
	jump read_rotary_switch_exit

read_rotary_switch_left:
	move RB 2    
    
read_rotary_switch_exit:
	move RA RB
	store RA rotary_switch
	ret
	
# ----------------------
# - READ FIRE SWITCH -
# ----------------------   
  
# 0=NOT PRESSED, 1=~PRESSED

read_fire_switch:
    move RB 0
    
	load RA ROTARY_DATA		   # fire pressed
	and RA 0x01	
	jumpz read_fire_switch_exit
	
	move RB 1
	
read_fire_switch_exit:	
	move RA RB
	store RA fire_switch
	ret
	
# --------------------
# - READ SNES SWITCH -
# -------------------- 	

read_snes_switch:
    move RA 0                  # start SNES update
    store RA SNES_START

read_snes_switch_wait:
    load RA SNES_STATUS        # wait for data
    and RA 0x01
    jumpnz read_snes_switch_wait
    
    load RA SNES_DATA          # read data
    store RA snes_switch
    ret

# ---------------------
# - READ PS2 KEYBOARD -
# ---------------------

read_keyboard:
    moved( RB, UPPER_BYTE_MASK )
    load RA PS2_DATA
    and RA RB
    jumpz read_keyboard_exit

    load RA PS2_DATA
    store RA PS2_DATA
    and RA 0xFF
    store RA key

read_keyboard_exit:
    ret
#>>

##################################
# DRAW LINE & CIRCLE SUBROUTINES #
##################################
#<<
# --------------
# - DRAW PIXEL -
# --------------

# draw pixel directly to frame buffer
# 
# colour                     : pixel_colour
# x location                 : pixel_x_pos
# y location                 : pixel_y_pos

draw_pixel:
#   ret
    load RA pixel_x_pos
    store RA PIXEL_X_REG
    load RA pixel_y_pos
    store RA PIXEL_Y_REG

#   cpu_colour_reg
    movea( RB, CPU_COLOUR_REG )
    load RA pixel_colour
    store RA (RB)

#   ctl reg 
    movea( RA, CPU_CTL_REG )
    move RB DRAW_PIXEL
    store RB (RA)

draw_pixel_wait:
    movea( RA, CPU_STATUS_REG )
    load RB (RA)
    and RB CTL_MASK
    jumpz draw_pixel_wait
    ret

# -------------
# - DRAW LINE -
# -------------

# Plot line between top points (X1,Y1) and (X0,Y0)
# Bresenham's line drawing algorithm
#
#   dx = abs(x2 - x1)
#   dy = abs(y2 - y1)
#   slope = dy > dx
#
#   if slope:
#     x1, y1 = y1, x1
#     x2, y2 = y2, x2
#
#   if x1 > x2:
#     x1, x2 = x2, x1
#     y1, y2 = y2, y1
#
#   dx = abs(x2 - x1)
#   dy = abs(y2 - y1)
#
#   error = dx // 2
#
#   y = y1
#   ystep = 1 if y1 < y2 else -1
#
#   for x in range(x1, x2 + 1):
#     if slope:
#       plot(y,x)
#     else:
#       plot(x,y)
#
#     error = error - dy
#     if error < 0:
#       y += ystep
#       error = error + dx

# colour                     : line_colour
# x location                 : line_x
# y location                 : line_y
# x0 location                : line_x0
# y0 location                : line_y0
# x1 location                : line_x1
# y1 location                : line_y1
# absolute (x1 - x0)         : line_dx 
# absolute (y1 - y0)         : line_dy
# error                      : line_error
# step                       : line_step
# slope                      : line_slope

# -----------
# - CALC DX -
# -----------

draw_line_dx:
    load RA line_x1          # test if X1 > X0
    subm RA line_x0
    move RB RA
    load RA msb_mask
    and RA RB              
    jumpnz draw_line_dx1

draw_line_dx0:
    load RA line_x1          # X1 > X0
    subm RA line_x0
    store RA line_dx         # calc DX
    jump draw_line_dx_exit

draw_line_dx1:
    load RA line_x0          # X0 > X1   
    subm RA line_x1 
    store RA line_dx         # calc DX

draw_line_dx_exit:
    ret

# -----------
# - CALC DY -
# -----------

draw_line_dy:
    load RA line_y1          # test if Y1 > Y0
    subm RA line_y0
    move RB RA
    load RA msb_mask
    and RA RB  
    jumpnz draw_line_dy1

draw_line_dy0:
    load RA line_y1          # Y1 > Y0     
    subm RA line_y0 
    store RA line_dy         # calc DY
    jump draw_line_dy_exit

draw_line_dy1:
    load RA line_y0          # Y0 > Y2     
    subm RA line_y1 
    store RA line_dy         # calc DY

draw_line_dy_exit:
    ret

# --------------------  
# - CALC LINE POINTS -
# --------------------

draw_line:
    call draw_line_dx
    call draw_line_dy

draw_line_slope:
    move RA 0
    store RA line_slope

    load RA line_dx          # is dy > dx
    subm RA line_dy   
    
#   use jumpc is available
    jumpc draw_line_slope_gt1   
        
#   move RB RA
#   load RA msb_mask
#   and RA RB
#   jumpnz draw_line_slope_gt1
    jump draw_line_slope_lt1

draw_line_slope_gt1:
    move RA 1
    store RA line_slope

    load RA line_y0         # x0,y0 = y0,x0
    move RB RA
    load RA line_x0
    store RA line_y0
    move RA RB 
    store RA line_x0

    load RA line_y1         # x1,y1 = y1,x1
    move RB RA
    load RA line_x1
    store RA line_y1
    move RA RB
    store RA line_x1 

draw_line_slope_lt1:
    load RA line_x1         # x0 > x1?
    subm RA line_x0

#   use jumpc is available
    jumpc draw_line_update1

#   move RB RA
#   load RA msb_mask
#   and RA RB
#   jumpnz draw_line_update1
    jump draw_line_start

draw_line_update1:
    move RC 0xFF
    load RA line_x0         # x0,x1 = x1,x0
    move RB RA
    load RA line_x1
    store RA line_x0
    move RA RB 
    store RA line_x1

    load RA line_y0         # y0,y1 = y1,y0
    move RB RA
    load RA line_y1
    store RA line_y0
    move RA RB 
    store RA line_y1

draw_line_start:
    call draw_line_dx
    call draw_line_dy

    load RA line_dx
    asr RA
    store RA line_error

    load RA line_y0
    store RA line_y
    load RA line_x0
    store RA line_x

    move RA 1
    store RA line_step

    load RA line_y0              
    subm RA line_y1

#   use jumpc is available
    jumpc draw_line_colour
 
#   move RB RA
#   load RA msb_mask
#   and RA RB
#   jumpnz draw_line_colour

    move RA 0xFF
    store RA line_step

draw_line_colour:
    load RA line_colour     # set line colour
    store RA pixel_colour

#    move RD 0xFF
#    load RA line_dx
#    move RD RA
#    load RA line_dy
#    move RD RA
#    load RA line_error
#    move RD RA
#    load RA line_step
#    move RD RA
#    load RA line_x0
#    move RD RA
#    load RA line_x1
#    move RD RA

draw_line_loop:
    load RA line_slope         # is dy > dx 
    and RA 0xFF
    jumpnz draw_line_loop_gt1
    jump draw_line_loop_lt1

draw_line_loop_gt1:
    load RA line_y          # set XY 
    store RA pixel_x_pos
    load RA line_x
    store RA pixel_y_pos
    jump draw_line_loop_update

draw_line_loop_lt1:
    load RA line_x          # set XY 
    store RA pixel_x_pos
    load RA line_y
    store RA pixel_y_pos

draw_line_loop_update:
    call draw_pixel          # plot XY

    load RA line_error
    subm RA line_dy
    store RA line_error

# use jumpc if available
    jumpc draw_line_error_lt0

#   move RB RA
#   load RA msb_mask
#   and RA RB
#   jumpnz draw_line_error_lt0
    jump draw_line_next

draw_line_error_lt0:
    load RA line_y
    addm RA line_step
    store RA line_y

    load RA line_error
    addm RA line_dx
    store RA line_error

draw_line_next:
    load RA line_x
    add RA 1
    store RA line_x

#   move RD 0xFF
#   load RA line_x
#   move RD RA
#   load RA line_y
#   move RD RA

    load RA line_x1
    subm RA line_x

# use jumpc if available
    jumpc draw_line_exit
 
#   move RB RA
#   load RA msb_mask
#   and RA RB
#   jumpnz draw_line_exit 
    jump draw_line_loop

draw_line_exit:
    ret

# ---------------
# - DRAW CIRCLE -
# ---------------

# Plot circle with mid-point x0, y0 and radius
# Bresenham's circle drawing algorithm

#  x = radius
#  y = 0
#  err = 0
#
#  while x >= y:
#    plot((x0 + x, y0 + y))  A
#    plot((x0 + y, y0 + x))  B
#    plot((x0 - y, y0 + x))  C
#    plot((x0 - x, y0 + y))  D
#    plot((x0 - x, y0 - y))  E
#    plot((x0 - y, y0 - x))  F
#    plot((x0 + y, y0 - x))  G 
#    plot((x0 + x, y0 - y))  H
#
#    y += 1
#    err += 1 + 2*y
#    if 2*(err-x) + 1 > 0:
#      x -= 1
#      err += 1 - 2*x

# colour            : circle_colour
# filled            : circle_filled
# x location        : circle_x
# y location        : circle_y
# midpoint x        : circle_x0
# midpoint y        : circle_y0
# radius            : circle_r
# error             : circle_error 

# A - B, C - D, E - F, G - H

#( p.x+x, p.y+y ) to ( p.x-x, p.y+y )
#       A                    D
#( p.x+y, p.y+x ) to ( p.x-y, p.y+x )
#       B                    C
#( p.x+x, p.y-y ) to ( p.x-x, p.y-y )
#       H                    E
#( p.x+y, p.y-x ) to ( p.x-y, p.y-x )
#       G                    F

draw_circle:
    load RA circle_r
    store RA circle_x
    move RA 0
    store RA circle_y
    store RA circle_error

    load RA circle_colour     # set line colour
    store RA line_colour
    store RA pixel_colour

draw_circle_loop:
    load RA circle_x
    subm RA circle_y

# use jumpc if available
    jumpc circle_exit

#   move RB RA
#   load RA msb_mask
#   and RA RB
#   jumpnz circle_exit

circle_A:
    load RA circle_x0
    addm RA circle_x
    store RA pixel_x_pos
    store RA circle_A_x   

    load RA circle_y0
    addm RA circle_y
    store RA pixel_y_pos
    store RA circle_A_y

    load RA circle_filled
    jumpnz circle_B
    call draw_pixel          # plot((x0 + x, y0 + y)) A

circle_B:
    load RA circle_x0
    addm RA circle_y
    store RA pixel_x_pos
    store RA circle_B_x   

    load RA circle_y0
    addm RA circle_x
    store RA pixel_y_pos
    store RA circle_B_y   

    load RA circle_filled
    jumpnz circle_C
    call draw_pixel          # plot((x0 + y, y0 + x)) B

circle_C:
    load RA circle_x0
    subm RA circle_y
    store RA pixel_x_pos
    store RA circle_C_x   

    load RA circle_y0
    addm RA circle_x
    store RA pixel_y_pos
    store RA circle_C_y   

    load RA circle_filled
    jumpnz circle_D
    call draw_pixel          # plot((x0 - y, y0 + x)) C

circle_D:
    load RA circle_x0
    subm RA circle_x
    store RA pixel_x_pos
    store RA circle_D_x   

    load RA circle_y0
    addm RA circle_y
    store RA pixel_y_pos
    store RA circle_D_y   

    load RA circle_filled
    jumpnz circle_E
    call draw_pixel          # plot((x0 - x, y0 + y)) D

circle_E:
    load RA circle_x0
    subm RA circle_x
    store RA pixel_x_pos
    store RA circle_E_x   

    load RA circle_y0
    subm RA circle_y
    store RA pixel_y_pos
    store RA circle_E_y   

    load RA circle_filled
    jumpnz circle_F
    call draw_pixel          # plot((x0 - x, y0 - y)) E

circle_F:
    load RA circle_x0
    subm RA circle_y
    store RA pixel_x_pos
    store RA circle_F_x   

    load RA circle_y0
    subm RA circle_x
    store RA pixel_y_pos
    store RA circle_F_y   

    load RA circle_filled
    jumpnz circle_G
    call draw_pixel          # plot((x0 - y, y0 - x)) F

circle_G:
    load RA circle_x0
    addm RA circle_y
    store RA pixel_x_pos
    store RA circle_G_x   

    load RA circle_y0
    subm RA circle_x
    store RA pixel_y_pos
    store RA circle_G_y   

    load RA circle_filled
    jumpnz circle_H
    call draw_pixel          # plot((x0 + y, y0 - x)) G

circle_H:
    load RA circle_x0
    addm RA circle_x
    store RA pixel_x_pos
    store RA circle_H_x   

    load RA circle_y0
    subm RA circle_y
    store RA pixel_y_pos
    store RA circle_H_y   

    load RA circle_filled
    jumpnz circle_fill
    call draw_pixel          # plot((x0 + x, y0 - y)) H
    jump circle_next

#( p.x+x, p.y+y ) to ( p.x-x, p.y+y )
#       A                    D
#( p.x+y, p.y+x ) to ( p.x-y, p.y+x )
#       B                    C
#( p.x+x, p.y-y ) to ( p.x-x, p.y-y )
#       H                    E
#( p.x+y, p.y-x ) to ( p.x-y, p.y-x )
#       G                    F

circle_fill:
    load RA circle_A_x     
    store RA line_x0 
    load RA circle_A_y
    store RA line_y0

    load RA circle_D_x            
    store RA line_x1 
    load RA circle_D_y  
    store RA line_y1

    call draw_line

    load RA circle_B_x     
    store RA line_x0 
    load RA circle_B_y
    store RA line_y0

    load RA circle_C_x            
    store RA line_x1 
    load RA circle_C_y  
    store RA line_y1

    call draw_line

    load RA circle_H_x     
    store RA line_x0 
    load RA circle_H_y
    store RA line_y0

    load RA circle_E_x            
    store RA line_x1 
    load RA circle_E_y  
    store RA line_y1

    call draw_line

    load RA circle_G_x     
    store RA line_x0 
    load RA circle_G_y
    store RA line_y0

    load RA circle_F_x            
    store RA line_x1 
    load RA circle_F_y  
    store RA line_y1

    call draw_line

#    y += 1
#    err += 1 + 2*y
#    if 2*(err-x) + 1 > 0:
#      x -= 1
#      err += 1 - 2*x

circle_next:
    load RA circle_y
    add RA 1
    store RA circle_y
    
    addm RA circle_y
    addm RA circle_error
    add RA 1
    store RA circle_error

    load RA circle_error
    subm RA circle_x
#   move RB RA
#   add RA RB
    add RA RA
    add RA 1

# use jumpc if availabl
    jumpc draw_circle_loop

#   move RB RA
#   load RA msb_mask
#   and RA RB
#   jumpnz draw_circle_loop

    load RA circle_x
    sub RA 1
    store RA circle_x

    addm RA circle_x
    move RB RA
    load RA circle_error
    add RA 1
    sub RA RB
    store RA circle_error
    jump draw_circle_loop

circle_exit:
    ret
#>>

####################
# LIST SUBROUTINES #
####################


####################
# MATH SUBROUTINES #
####################


####################
# GAME SUBROUTINES #
####################

# ------------------- 
# - DRAW BOB SCREEN -
# -------------------

draw_bob_screen:
    move RA GREEN
    store RA circle_colour

    move RA 80              
    store RA circle_x0 
    move RA 40
    store RA circle_y0
    move RA 28
    store RA circle_r

    call draw_circle

    move RA WHITE
    store RA circle_colour

    move RA 75              
    store RA circle_x0 
    move RA 35
    store RA circle_y0
    move RA 8
    store RA circle_r

    call draw_circle

    move RA 95              
    store RA circle_x0 
    move RA 35
    store RA circle_y0
    move RA 8
    store RA circle_r

    call draw_circle

    move RA BLACK
    store RA circle_colour

    move RA 75              
    store RA circle_x0 
    move RA 35
    store RA circle_y0
    move RA 4
    store RA circle_r

    call draw_circle

    move RA 95              
    store RA circle_x0 
    move RA 35
    store RA circle_y0
    move RA 4
    store RA circle_r

    call draw_circle

	draw_tile( RED, eval( 0 + ( 8 * 6 ) ), 78, B_CHAR )
	draw_tile( RED, eval( 0 + ( 8 * 7 ) ), 78, o_CHAR )
	draw_tile( RED, eval( 0 + ( 8 * 8 ) ), 78, b_CHAR )
	draw_tile( RED, eval( 0 + ( 8 * 10 ) ), 78, G_CHAR )
	draw_tile( RED, eval( 0 + ( 8 * 11 ) ), 78, a_CHAR )
	draw_tile( RED, eval( 0 + ( 8 * 12 ) ), 78, m_CHAR )
	draw_tile( RED, eval( 0 + ( 8 * 13 ) ), 78, e_CHAR )
	draw_tile( RED, eval( 0 + ( 8 * 14 ) ), 78, s_CHAR )

	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 1 ) ), 90, a_CHAR )

	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 3 ) ), 90, M_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 4 ) ), 90, i_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 5 ) ), 90, k_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 6 ) ), 90, e_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 7 ) ), 90, F_CHAR )

	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 9 ) ), 90, P_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 10 ) ), 90, r_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 11 ) ), 90, o_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 12 ) ), 90, d_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 13 ) ), 90, u_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 14 ) ), 90, c_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 15 ) ), 90, t_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 16 ) ), 90, i_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 17 ) ), 90, o_CHAR )
	draw_tile( LIGHT_GREY, eval( 0 + ( 8 * 18 ) ), 90, n_CHAR )

    ret

# ------------
# - INIT LCD -
# ------------ 

init_lcd:
    movea( RA, init_string )
    store RA lcd_pntr
    move RA 1
    store RA lcd_config
    call lcd_tx

    #call lcd_line_2

    movea( RA, message_string )
    store RA lcd_pntr
    move RA 0
    store RA lcd_config
    call lcd_tx

    ret

# ------------- 
# - INIT GAME -
# -------------

init_game:
    move RA 0
    store RA player_O_score
    store RA player_X_score
	store RA player
    store RA position
    store RA win
    store RA finish
    store RA restart

    #store RA player_O_try
    #store RA player_X_try

    load RA player_O_try
    add RA 1
    store RA player_O_try

    load RA player_X_try
    add RA 2
    store RA player_X_try

init_grid:
    move RA 0
    movea( RB, grid_state + 0 )
    store RA (RB)
    movea( RB, grid_state + 1 )
    store RA (RB)
    movea( RB, grid_state + 2 )
    store RA (RB)
    movea( RB, grid_state + 3 )
    store RA (RB)
    movea( RB, grid_state + 4 )
    store RA (RB)
    movea( RB, grid_state + 5 )
    store RA (RB)
    movea( RB, grid_state + 6 )
    store RA (RB)
    movea( RB, grid_state + 7 )
    store RA (RB)
    movea( RB, grid_state + 8 )
    store RA (RB)
    ret

# --------------- 
# - GAME SCREEN -
# ---------------

draw_game_screen:
	draw_tile( TURQUOISE, eval( ( 8 * 1  ) ), eval( ( 8 * 0 ) ), P_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 2  ) ), eval( ( 8 * 0 ) ), l_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 3  ) ), eval( ( 8 * 0 ) ), a_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 4  ) ), eval( ( 8 * 0 ) ), y_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 5  ) ), eval( ( 8 * 0 ) ), e_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 6  ) ), eval( ( 8 * 0 ) ), r_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 7  ) ), eval( ( 8 * 0 ) ), sp_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 8  ) ), eval( ( 8 * 0 ) ), O_CHAR )

	draw_tile( LIGHT_GREY, eval( ( 8 * 1  ) ), eval( ( 8 * 1 ) ), zero_CHAR )
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), zero_CHAR )

	draw_tile( TURQUOISE, eval( ( 8 * 11  ) ), eval( ( 8 * 0 ) ), P_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 12  ) ), eval( ( 8 * 0 ) ), l_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 13  ) ), eval( ( 8 * 0 ) ), a_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 14  ) ), eval( ( 8 * 0 ) ), y_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 15  ) ), eval( ( 8 * 0 ) ), e_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 16  ) ), eval( ( 8 * 0 ) ), r_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 17  ) ), eval( ( 8 * 0 ) ), sp_CHAR )
	draw_tile( TURQUOISE, eval( ( 8 * 18  ) ), eval( ( 8 * 0 ) ), X_CHAR )

	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), zero_CHAR )
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), zero_CHAR )

draw_game_grid:
	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 3 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 3 ) ), LINE_2_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 3 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 3 ) ), LINE_2_CHAR )

	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 4 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 4 ) ), LINE_2_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 4 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 4 ) ), LINE_2_CHAR )

	draw_tile( RED, eval( ( 8 * 4  ) ), eval( ( 8 * 5 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 5  ) ), eval( ( 8 * 5 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 6  ) ), eval( ( 8 * 5 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 5 ) ), CORNER_3_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 5 ) ), CORNER_1_CHAR )
	draw_tile( RED, eval( ( 8 * 9  ) ), eval( ( 8 * 5 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 10 ) ), eval( ( 8 * 5 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 5 ) ), CORNER_3_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 5 ) ), CORNER_1_CHAR )
	draw_tile( RED, eval( ( 8 * 13 ) ), eval( ( 8 * 5 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 14 ) ), eval( ( 8 * 5 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 15 ) ), eval( ( 8 * 5 ) ), LINE_3_CHAR )

	draw_tile( RED, eval( ( 8 * 4  ) ), eval( ( 8 * 6 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 5  ) ), eval( ( 8 * 6 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 6  ) ), eval( ( 8 * 6 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 6 ) ), CORNER_4_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 6 ) ), CORNER_2_CHAR )
	draw_tile( RED, eval( ( 8 * 9  ) ), eval( ( 8 * 6 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 10 ) ), eval( ( 8 * 6 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 6 ) ), CORNER_4_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 6 ) ), CORNER_2_CHAR )
	draw_tile( RED, eval( ( 8 * 13 ) ), eval( ( 8 * 6 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 14 ) ), eval( ( 8 * 6 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 15 ) ), eval( ( 8 * 6 ) ), LINE_4_CHAR )

	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 7 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 7 ) ), LINE_2_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 7 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 7 ) ), LINE_2_CHAR )

	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 8 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 8 ) ), LINE_2_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 8 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 8 ) ), LINE_2_CHAR )

	draw_tile( RED, eval( ( 8 * 4  ) ), eval( ( 8 * 9 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 5  ) ), eval( ( 8 * 9 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 6  ) ), eval( ( 8 * 9 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 9 ) ), CORNER_3_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 9 ) ), CORNER_1_CHAR )
	draw_tile( RED, eval( ( 8 * 9  ) ), eval( ( 8 * 9 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 10 ) ), eval( ( 8 * 9 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 9 ) ), CORNER_3_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 9 ) ), CORNER_1_CHAR )
	draw_tile( RED, eval( ( 8 * 13 ) ), eval( ( 8 * 9 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 14 ) ), eval( ( 8 * 9 ) ), LINE_3_CHAR )
	draw_tile( RED, eval( ( 8 * 15 ) ), eval( ( 8 * 9 ) ), LINE_3_CHAR )

	draw_tile( RED, eval( ( 8 * 4  ) ), eval( ( 8 * 10 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 5  ) ), eval( ( 8 * 10 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 6  ) ), eval( ( 8 * 10 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 10 ) ), CORNER_4_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 10 ) ), CORNER_2_CHAR )
	draw_tile( RED, eval( ( 8 * 9  ) ), eval( ( 8 * 10 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 10 ) ), eval( ( 8 * 10 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 10 ) ), CORNER_4_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 10 ) ), CORNER_2_CHAR )
	draw_tile( RED, eval( ( 8 * 13 ) ), eval( ( 8 * 10 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 14 ) ), eval( ( 8 * 10 ) ), LINE_4_CHAR )
	draw_tile( RED, eval( ( 8 * 15 ) ), eval( ( 8 * 10 ) ), LINE_4_CHAR )

	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 11 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 11 ) ), LINE_2_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 11 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 11 ) ), LINE_2_CHAR )

	draw_tile( RED, eval( ( 8 * 7  ) ), eval( ( 8 * 12 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 8  ) ), eval( ( 8 * 12 ) ), LINE_2_CHAR )
	draw_tile( RED, eval( ( 8 * 11 ) ), eval( ( 8 * 12 ) ), LINE_1_CHAR )
	draw_tile( RED, eval( ( 8 * 12 ) ), eval( ( 8 * 12 ) ), LINE_2_CHAR )

	ret

# --------------------
# - INC PLAYER SCORE -
# --------------------

inc_player_score: 
 	load RA player_X_score
    sub RA 99
    jumpz inc_player_score_restart
   
 	load RA player_O_score
    sub RA 99
    jumpz inc_player_score_restart

    load RA player                     # select player 0 or X
    and RA 0xFF
    jumpz inc_player_score_O

inc_player_score_X:
	load RA player_X_score
	add RA 1
	store RA player_X_score

    jump inc_player_score_update

inc_player_score_O:
	load RA player_O_score
	add RA 1
	store RA player_O_score

inc_player_score_update:
	call bin_2_dec                     # convert (passed in RA)

	load RA bin_2_dec_1s_cnt
	and RA 0xFF
	jumpz inc_player_score_1s_0
	sub RA 1
	jumpz inc_player_score_1s_1
	sub RA 1
	jumpz inc_player_score_1s_2
	sub RA 1
	jumpz inc_player_score_1s_3
	sub RA 1
	jumpz inc_player_score_1s_4
	sub RA 1
	jumpz inc_player_score_1s_5
	sub RA 1
	jumpz inc_player_score_1s_6
	sub RA 1
	jumpz inc_player_score_1s_7
	sub RA 1
	jumpz inc_player_score_1s_8
	sub RA 1
	jumpz inc_player_score_1s_9
	jump inc_player_score_1s_0

inc_player_score_1s_0:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_0_O

inc_player_score_1s_0_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), zero_CHAR )
    jump update_10s_digit

inc_player_score_1s_0_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), zero_CHAR )
	jump update_10s_digit

inc_player_score_1s_1:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_1_O

inc_player_score_1s_1_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), one_CHAR )
    jump update_10s_digit

inc_player_score_1s_1_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), one_CHAR )
	jump update_10s_digit

inc_player_score_1s_2:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_2_O

inc_player_score_1s_2_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), two_CHAR )
    jump update_10s_digit

inc_player_score_1s_2_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), two_CHAR )
	jump update_10s_digit

inc_player_score_1s_3:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_3_O

inc_player_score_1s_3_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), three_CHAR )
    jump update_10s_digit

inc_player_score_1s_3_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), three_CHAR )
	jump update_10s_digit

inc_player_score_1s_4:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_4_O

inc_player_score_1s_4_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), four_CHAR )
    jump update_10s_digit

inc_player_score_1s_4_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), four_CHAR )
	jump update_10s_digit

inc_player_score_1s_5:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_5_O

inc_player_score_1s_5_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), five_CHAR )
    jump update_10s_digit

inc_player_score_1s_5_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), five_CHAR )
	jump update_10s_digit

inc_player_score_1s_6:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_6_O

inc_player_score_1s_6_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), six_CHAR )
    jump update_10s_digit

inc_player_score_1s_6_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), six_CHAR )
	jump update_10s_digit

inc_player_score_1s_7:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_7_O

inc_player_score_1s_7_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), seven_CHAR )
    jump update_10s_digit

inc_player_score_1s_7_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), seven_CHAR )
	jump update_10s_digit

inc_player_score_1s_8:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_8_O

inc_player_score_1s_8_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), eight_CHAR )
    jump update_10s_digit

inc_player_score_1s_8_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), eight_CHAR )
	jump update_10s_digit

inc_player_score_1s_9:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_1s_9_O

inc_player_score_1s_9_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 12  ) ), eval( ( 8 * 1 ) ), nine_CHAR )
    jump update_10s_digit

inc_player_score_1s_9_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 2  ) ), eval( ( 8 * 1 ) ), nine_CHAR )

update_10s_digit:
	load RA bin_2_dec_10s_cnt
	and RA 0xFF
	jumpz inc_player_score_10s_0
	sub RA 1
	jumpz inc_player_score_10s_1
	sub RA 1
	jumpz inc_player_score_10s_2
	sub RA 1
	jumpz inc_player_score_10s_3
	sub RA 1
	jumpz inc_player_score_10s_4
	sub RA 1
	jumpz inc_player_score_10s_5
	sub RA 1
	jumpz inc_player_score_10s_6
	sub RA 1
	jumpz inc_player_score_10s_7
	sub RA 1
	jumpz inc_player_score_10s_8
	sub RA 1
	jumpz inc_player_score_10s_9
	jump inc_player_score_10s_0

inc_player_score_10s_0:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_0_O

inc_player_score_10s_0_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), zero_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_0_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1  ) ), eval( ( 8 * 1 ) ), zero_CHAR )
	jump inc_player_score_exit

inc_player_score_10s_1:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_1_O

inc_player_score_10s_1_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), one_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_1_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1  ) ), eval( ( 8 * 1 ) ), one_CHAR )
	jump inc_player_score_exit

inc_player_score_10s_2:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_2_O

inc_player_score_10s_2_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), two_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_2_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1  ) ), eval( ( 8 * 1 ) ), two_CHAR )
	jump inc_player_score_exit

inc_player_score_10s_3:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_3_O

inc_player_score_10s_3_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), three_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_3_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1  ) ), eval( ( 8 * 1 ) ), three_CHAR )
	jump inc_player_score_exit

inc_player_score_10s_4:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_4_O

inc_player_score_10s_4_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), four_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_4_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1 ) ), eval( ( 8 * 1 ) ), four_CHAR )
	jump inc_player_score_exit

inc_player_score_10s_5:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_5_O

inc_player_score_10s_5_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), five_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_5_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1 ) ), eval( ( 8 * 1 ) ), five_CHAR )
	jump inc_player_score_exit

inc_player_score_10s_6:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_6_O

inc_player_score_10s_6_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), six_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_6_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1  ) ), eval( ( 8 * 1 ) ), six_CHAR )
	jump inc_player_score_exit

inc_player_score_10s_7:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_7_O

inc_player_score_10s_7_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), seven_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_7_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1 ) ), eval( ( 8 * 1 ) ), seven_CHAR )
	jump inc_player_score_exit

inc_player_score_10s_8:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_8_O

inc_player_score_10s_8_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), eight_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_8_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1 ) ), eval( ( 8 * 1 ) ), eight_CHAR )
	jump inc_player_score_exit

inc_player_score_10s_9:
    load RA player 
    and RA 0xFF
    jumpz inc_player_score_10s_9_O

inc_player_score_10s_9_X:
	draw_tile( LIGHT_GREY, eval( ( 8 * 11  ) ), eval( ( 8 * 1 ) ), nine_CHAR )
    jump inc_player_score_exit

inc_player_score_10s_9_O:
	draw_tile( LIGHT_GREY, eval( ( 8 * 1  ) ), eval( ( 8 * 1 ) ), nine_CHAR )
    jump inc_player_score_exit

inc_player_score_restart:
    move RA 1
    store RA restart

inc_player_score_exit:
	ret


# ----------
# - DRAW 0 -
# ----------

# 0 | 1 | 2
# ----------
# 3 | 4 | 5
# ----------
# 6 | 7 | 8


draw_O:
    load RA position
    sub RA 0
    jumpnz draw_O_1

    # 0
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 ) ), eval( ( 8 * 3 ) ), CORNER_2_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 ) ), eval( ( 8 * 3 ) ), CORNER_4_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 ) ), eval( ( 8 * 4 ) ), CORNER_1_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 ) ), eval( ( 8 * 4 ) ), CORNER_3_CHAR )
    ret

draw_O_1:
    load RA position
    sub RA 1
    jumpnz draw_O_2

    #1
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 3 ) ), CORNER_2_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 3 ) ), CORNER_4_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 4 ) ), CORNER_1_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 4 ) ), CORNER_3_CHAR )
    ret

draw_O_2:
    load RA position
    sub RA 2
    jumpnz draw_O_3

    # 2
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 3 ) ), CORNER_2_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 3 ) ), CORNER_4_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 4 ) ), CORNER_1_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 4 ) ), CORNER_3_CHAR )
    ret

draw_O_3:
    load RA position
    sub RA 3
    jumpnz draw_O_4

    # 3
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 )  ), eval( ( 8 * 7 ) ), CORNER_2_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 )  ), eval( ( 8 * 7 ) ), CORNER_4_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 )  ), eval( ( 8 * 8 ) ), CORNER_1_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 )  ), eval( ( 8 * 8 ) ), CORNER_3_CHAR )
    ret

draw_O_4:
    load RA position
    sub RA 4
    jumpnz draw_O_5

    # 4
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 7 ) ), CORNER_2_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 7 ) ), CORNER_4_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 8 ) ), CORNER_1_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 8 ) ), CORNER_3_CHAR )
    ret

draw_O_5:
    load RA position
    sub RA 5
    jumpnz draw_O_6

    # 5
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 7 ) ), CORNER_2_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 7 ) ), CORNER_4_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 8 ) ), CORNER_1_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 8 ) ), CORNER_3_CHAR )
    ret

draw_O_6:
    load RA position
    sub RA 6
    jumpnz draw_O_7

    # 6
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 )  ), eval( ( 8 * 11 ) ), CORNER_2_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 )  ), eval( ( 8 * 11 ) ), CORNER_4_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 )  ), eval( ( 8 * 12 ) ), CORNER_1_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 )  ), eval( ( 8 * 12 ) ), CORNER_3_CHAR )
    ret

draw_O_7:
    load RA position
    sub RA 7
    jumpnz draw_O_8

    # 7
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 11 ) ), CORNER_2_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 11 ) ), CORNER_4_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 12 ) ), CORNER_1_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 12 ) ), CORNER_3_CHAR )
    ret

draw_O_8:
    load RA position
    sub RA 8
    jumpnz draw_O_exit

    # 8
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 11 ) ), CORNER_2_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 11 ) ), CORNER_4_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 12 ) ), CORNER_1_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 12 ) ), CORNER_3_CHAR )

draw_O_exit:
    ret

# ----------
# - DRAW X -
# ----------

# 0 | 1 | 2
# ----------
# 3 | 4 | 5
# ----------
# 6 | 7 | 8


draw_X:
    load RA position
    sub RA 0
    jumpnz draw_X_1

    # 0
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 ) ), eval( ( 8 * 3 ) ), LINE_6_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 ) ), eval( ( 8 * 3 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 ) ), eval( ( 8 * 4 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 ) ), eval( ( 8 * 4 ) ), LINE_6_CHAR )
    ret

draw_X_1:
    load RA position
    sub RA 1
    jumpnz draw_X_2

    #1
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 3 ) ), LINE_6_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 3 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 4 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 4 ) ), LINE_6_CHAR )
    ret

draw_X_2:
    load RA position
    sub RA 2
    jumpnz draw_X_3

    # 2
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 3 ) ), LINE_6_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 3 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 4 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 4 ) ), LINE_6_CHAR )
    ret

draw_X_3:
    load RA position
    sub RA 3
    jumpnz draw_X_4

    # 3
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 )  ), eval( ( 8 * 7 ) ), LINE_6_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 )  ), eval( ( 8 * 7 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 )  ), eval( ( 8 * 8 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 )  ), eval( ( 8 * 8 ) ), LINE_6_CHAR )
    ret

draw_X_4:
    load RA position
    sub RA 4
    jumpnz draw_X_5

    # 4
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 7 ) ), LINE_6_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 7 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 8 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 8 ) ), LINE_6_CHAR )
    ret

draw_X_5:
    load RA position
    sub RA 5
    jumpnz draw_X_6

    # 5
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 7 ) ), LINE_6_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 7 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 8 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 8 ) ), LINE_6_CHAR )
    ret

draw_X_6:
    load RA position
    sub RA 6
    jumpnz draw_X_7

    # 6
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 )  ), eval( ( 8 * 11 ) ), LINE_6_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 )  ), eval( ( 8 * 11 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 5 )  ), eval( ( 8 * 12 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 6 )  ), eval( ( 8 * 12 ) ), LINE_6_CHAR )
    ret

draw_X_7:
    load RA position
    sub RA 7
    jumpnz draw_X_8

    # 7
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 11 ) ), LINE_6_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 11 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 9 )  ), eval( ( 8 * 12 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 10 ) ), eval( ( 8 * 12 ) ), LINE_6_CHAR )
    ret

draw_X_8:
    load RA position
    sub RA 8
    jumpnz draw_X_exit

    # 8
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 11 ) ), LINE_6_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 11 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 13 ) ), eval( ( 8 * 12 ) ), LINE_5_CHAR )
	draw_tile( LIGHT_GREEN, eval( ( 8 * 14 ) ), eval( ( 8 * 12 ) ), LINE_6_CHAR )

draw_X_exit:
    ret

# ---------------
# - MAKE MOVE O -
# ---------------
# 0000 0000 = empty  0000 0001 = O  0001 0000 = X  
#     0                  1              16

make_move_O:
    movea( RB, random_O )       # set random_O as base address

    load RA player_O_try        # load try count (0 - 63)
    add RA 1                    # inc
    and RA 0x3F                 # cap
    store RA player_O_try       # save  
    add RB RA                   # random base addr + try count
    load RA (RB)                # get random value
    store RA position

    movea( RB, grid_state )     # set grid_state
    add RB RA                   # offset by random value
    load RA (RB)                # get state
    and RA 0xFF                 # test if free i.e. 0
    jumpnz make_move_O          # if taken repeat

    move RA 0x01                # update grid
    store RA (RB)
    call draw_O                 # draw O                
    ret

# ---------------
# - MAKE MOVE X -
# ---------------
# 0000 0000 = empty  0000 0001 = O  0001 0000 = X  
#     0                  1              16

make_move_X:
    movea( RB, random_X )       # set random_O as base address

    load RA player_X_try        # load try count (0 - 63)
    add RA 1                    # inc
    and RA 0x3F                 # cap
    store RA player_X_try       # save  
    add RB RA                   # random base addr + try count
    load RA (RB)                # get random value
    store RA position

    movea( RB, grid_state )     # set grid_state
    add RB RA                   # offset by random value
    load RA (RB)                # get state
    and RA 0xFF                 # test if free i.e. 0
    jumpnz make_move_X          # if taken repeat

    move RA 0x10                # update grid
    store RA (RB)
    call draw_X                 # draw O                
    ret

# -----------------------
# - CHECK WIN CONDITION -
# -----------------------

# 0 | 1 | 2
# ----------
# 3 | 4 | 5
# ----------
# 6 | 7 | 8

# 012   345   678
# 036   147   258
# 048   246

# 0000 0000 = empty  0000 0001 = O  0001 0000 = X  
#     0                  1              16

check_win_condition:
    move RA 0
    store RA win

    move RC 0

    movea( RA, grid_state )     # access 0
    load RB (RA)
    add RC RB

    add RA 1                    # access 1
    load RB (RA)
    add RC RB

    add RA 1                    # access 2
    load RB (RA)
    add RC RB

    move RD RC
    and RC 0x0F
    sub RC 0x03
    jumpz check_win_condition_0
    move RC RD
    and RC 0xF0
    sub RC 0x30
    jumpz check_win_condition_0

    move RC 0

    movea( RA, grid_state )     
    add RA 3
    load RB (RA)                # access 3
    add RC RB

    add RA 1                    # access 4
    load RB (RA)
    add RC RB

    add RA 1                    # access 5
    load RB (RA)
    add RC RB

    move RD RC
    and RC 0x0F
    sub RC 0x03
    jumpz check_win_condition_1
    move RC RD
    and RC 0xF0
    sub RC 0x30
    jumpz check_win_condition_1

    move RC 0

    movea( RA, grid_state )     
    add RA 6
    load RB (RA)                # access 6
    add RC RB

    add RA 1                    # access 7
    load RB (RA)
    add RC RB

    add RA 1                    # access 8
    load RB (RA)
    add RC RB

    move RD RC
    and RC 0x0F
    sub RC 0x03
    jumpz check_win_condition_2
    move RC RD
    and RC 0xF0
    sub RC 0x30
    jumpz check_win_condition_2  

    move RC 0

    movea( RA, grid_state )     
    load RB (RA)                # access 0
    add RC RB

    add RA 3                    # access 3
    load RB (RA)
    add RC RB

    add RA 3                    # access 6
    load RB (RA)
    add RC RB

    move RD RC
    and RC 0x0F
    sub RC 0x03
    jumpz check_win_condition_3
    move RC RD
    and RC 0xF0
    sub RC 0x30
    jumpz check_win_condition_3 

    move RC 0

    movea( RA, grid_state )    
    add RA 1 
    load RB (RA)                # access 1
    add RC RB

    add RA 3                    # access 4
    load RB (RA)
    add RC RB

    add RA 3                    # access 7
    load RB (RA)
    add RC RB

    move RD RC
    and RC 0x0F
    sub RC 0x03
    jumpz check_win_condition_4
    move RC RD
    and RC 0xF0
    sub RC 0x30
    jumpz check_win_condition_4

    move RC 0

    movea( RA, grid_state )    
    add RA 2 
    load RB (RA)                # access 2
    add RC RB

    add RA 3                    # access 5
    load RB (RA)
    add RC RB

    add RA 3                    # access 8
    load RB (RA)
    add RC RB

    move RD RC
    and RC 0x0F
    sub RC 0x03
    jumpz check_win_condition_5
    move RC RD
    and RC 0xF0
    sub RC 0x30
    jumpz check_win_condition_5

    move RC 0

    movea( RA, grid_state )    
    load RB (RA)                # access 0
    add RC RB

    add RA 4                    # access 4
    load RB (RA)
    add RC RB

    add RA 4                    # access 8
    load RB (RA)
    add RC RB

    move RD RC
    and RC 0x0F
    sub RC 0x03
    jumpz check_win_condition_6
    move RC RD
    and RC 0xF0
    sub RC 0x30
    jumpz check_win_condition_6

    move RC 0

    movea( RA, grid_state )   
    add RA 2 
    load RB (RA)                # access 2
    add RC RB

    add RA 2                    # access 4
    load RB (RA)
    add RC RB

    add RA 2                    # access 6
    load RB (RA)
    add RC RB

    move RD RC
    and RC 0x0F
    sub RC 0x03
    jumpz check_win_condition_7
    move RC RD
    and RC 0xF0
    sub RC 0x30
    jumpz check_win_condition_7
    ret

check_win_condition_0:
    move RA PINK
    store RA line_colour             # 012

    move RA 40            
    store RA line_x0 
    move RA 32
    store RA line_y0

    move RA 120           
    store RA line_x1 
    move RA 32
    store RA line_y1

    call draw_line

    move RA 1
    store RA win

    call inc_player_score
    ret

check_win_condition_1:
    move RA PINK
    store RA line_colour          # 345

    move RA 40            
    store RA line_x0 
    move RA 63
    store RA line_y0

    move RA 120           
    store RA line_x1 
    move RA 63
    store RA line_y1

    call draw_line

    move RA 1
    store RA win

    call inc_player_score
    ret

check_win_condition_2:
    move RA PINK
    store RA line_colour          # 678

    move RA 40            
    store RA line_x0 
    move RA 95
    store RA line_y0

    move RA 120          
    store RA line_x1 
    move RA 95
    store RA line_y1

    call draw_line

    move RA 1
    store RA win

    call inc_player_score
    ret

check_win_condition_3:
    move RA PINK
    store RA line_colour          # 036

    move RA 48            
    store RA line_x0 
    move RA 25
    store RA line_y0

    move RA 48           
    store RA line_x1 
    move RA 100
    store RA line_y1

    call draw_line

    move RA 1
    store RA win

    call inc_player_score
    ret

check_win_condition_4:
    move RA PINK
    store RA line_colour          # 147

    move RA 80           
    store RA line_x0 
    move RA 25
    store RA line_y0

    move RA 80           
    store RA line_x1 
    move RA 100
    store RA line_y1

    call draw_line

    move RA 1
    store RA win

    call inc_player_score
    ret

check_win_condition_5:
    move RA PINK
    store RA line_colour          # 258

    move RA 111            
    store RA line_x0 
    move RA 25
    store RA line_y0

    move RA 111           
    store RA line_x1 
    move RA 100
    store RA line_y1

    call draw_line

    move RA 1
    store RA win

    call inc_player_score
    ret

check_win_condition_6:
    move RA PINK
    store RA line_colour          # 048

    move RA 40            
    store RA line_x0 
    move RA 24
    store RA line_y0

    move RA 120           
    store RA line_x1 
    move RA 103
    store RA line_y1

    call draw_line

    move RA 1
    store RA win

    call inc_player_score
    ret

check_win_condition_7:
    move RA PINK
    store RA line_colour          # 346

    move RA 40            
    store RA line_x0 
    move RA 103
    store RA line_y0

    move RA 120           
    store RA line_x1 
    move RA 24
    store RA line_y1

    call draw_line

    move RA 1
    store RA win

    call inc_player_score
    ret


# ------------------------
# - CHECK DRAW CONDITION -
# ------------------------

# 0 | 1 | 2
# ----------
# 3 | 4 | 5
# ----------
# 6 | 7 | 8

# 0000 0000 = empty  0000 0001 = O  0001 0000 = X  
#     0                  1              16

check_draw_condition:
    move RA 0
    store RA finish
    
    movea( RB, grid_state + 0 )
    load RA (RB)
    and RA 0xFF
    jumpz check_draw_condition_false

    movea( RB, grid_state + 1 )
    load RA (RB)
    and RA 0xFF
    jumpz check_draw_condition_false

    movea( RB, grid_state + 2 )
    load RA (RB)
    and RA 0xFF
    jumpz check_draw_condition_false

    movea( RB, grid_state + 3 )
    load RA (RB)
    and RA 0xFF
    jumpz check_draw_condition_false

    movea( RB, grid_state + 4 )
    load RA (RB)
    and RA 0xFF
    jumpz check_draw_condition_false

    movea( RB, grid_state + 5 )
    load RA (RB)
    and RA 0xFF
    jumpz check_draw_condition_false

    movea( RB, grid_state + 6 )
    load RA (RB)
    and RA 0xFF
    jumpz check_draw_condition_false

    movea( RB, grid_state + 7 )
    load RA (RB)
    and RA 0xFF
    jumpz check_draw_condition_false

    movea( RB, grid_state + 8 )
    load RA (RB)
    and RA 0xFF
    jumpz check_draw_condition_false

check_draw_condition_true:
    move RA 1
    store RA finish

check_draw_condition_false:
    ret


###########################
# CONSTANTS AND VARIABLES #
###########################
#<<
negative_sign_extend:
	.data 0xFF00

random_mask:
    .data 0xFFFC

msb_mask:
    .data 0x8000

count:
    .data 0

line:
    .data 0

# -------------------
# - Block Variables -
# -------------------

block_colour:
    .data 0

block_x_top_pos:
    .data 0

block_x_bottom_pos:
    .data 0

block_y_top_pos:
    .data 0

block_y_bottom_pos:
    .data 0

block_start_address:
    .data 0

block_width:
    .data 0

block_depth:
    .data 0

block_destination_address:
    .data 0

# ---------------------
# - Convert Variables -
# ---------------------

word:
    .data 0

byte:
    .data 0

nibble:
    .data 0

bin_2_dec_1s_cnt:
	.data 0

bin_2_dec_10s_cnt:
	.data 0

bin_2_dec_100s_cnt:
	.data 0

# --------------------
# - String Variables -
# --------------------

srcAddr:
    .data 0x00

destAddr:
    .data 0x00

# -------------------------
# - Serial Port Variables -
# -------------------------

txBufferIndex:
    .data 0x00

rxBufferIndex:
    .data 0x00

keyPressed:
    .data 0x00

txBuffer:
    space( 64 )

rxBuffer:
    space( 64 )

# --------------------
# - Bin to Hex table -
# --------------------

nibble2HexTable:
    .data 0x30    # '0'
    .data 0x31    # '1' 
    .data 0x32    # '2'
    .data 0x33    # '3' 
    .data 0x34    # '4'
    .data 0x35    # '5' 
    .data 0x36    # '6'
    .data 0x37    # '7' 
    .data 0x38    # '8'
    .data 0x39    # '9' 
    .data 0x41    # 'A'
    .data 0x42    # 'B' 
    .data 0x43    # 'C'
    .data 0x44    # 'D' 
    .data 0x45    # 'E'
    .data 0x46    # 'F' 

# ---------------
# - Test String -
# ---------------

hello:
    .data 0x48    # H
    .data 0x65    # e
    .data 0x6C    # l
    .data 0x6C    # l
    .data 0x6F    # 0
    .data 0x20    # SPACE
    .data 0x57    # W
    .data 0x6F    # o
    .data 0x72    # r
    .data 0x6C    # l
    .data 0x64    # d
    .data 0x0A    # LF
    .data 0x0D    # CR
    .data 0x00    # NULL

# ------------------
# - Welcome string -
# ------------------

welcome:
    .data 0x0A    # LF
    .data 0x0D    # CR
    .data 0x53    # S
    .data 0x69    # i
    .data 0x6D    # m
    .data 0x70    # p
    .data 0x6C    # l
    .data 0x65    # e
    .data 0x43    # C
    .data 0x50    # P
    .data 0x55    # U
    .data 0x20    # SPACE
    .data 0x44    # D
    .data 0x65    # e
    .data 0x62    # b
    .data 0x75    # u
    .data 0x67    # g
    .data 0x0A    # LF
    .data 0x0D    # CR
    .data 0x00    # NULL

# ------------------
# - Software delay -
# ------------------

delay_low_count:
	.data 0

delay_high_count:
	.data 0

# ---------
# - Pixel -
# ---------

pixel_colour:
    .data 0

pixel_x_pos:
    .data 0

pixel_y_pos:
    .data 0

# ---------
# - Line  -
# ---------

line_colour:
    .data 0

line_x:
    .data 0

line_y:
    .data 0

line_x0:
    .data 0

line_y0:
    .data 0

line_x1:
    .data 0

line_y1:
    .data 0

line_dx:
    .data 0

line_dy:
    .data 0

line_error:
    .data 0

line_step:
    .data 0

line_slope:
    .data 0

# ----------
# - Circle -
# ----------

circle_colour:
    .data 0

circle_filled:
    .data 0

circle_x:
    .data 0

circle_y:
    .data 0

circle_x0:
    .data 0

circle_y0:
    .data 0

circle_r:
    .data 0

circle_error:
    .data 0 

circle_A_x:
    .data 0 

circle_A_y:
    .data 0 

circle_B_x:
    .data 0 

circle_B_y:
    .data 0 

circle_C_x:
    .data 0 

circle_C_y:
    .data 0 

circle_D_x:
    .data 0 

circle_D_y:
    .data 0 

circle_E_x:
    .data 0 

circle_E_y:
    .data 0 

circle_F_x:
    .data 0 

circle_F_y:
    .data 0 

circle_G_x:
    .data 0 

circle_G_y:
    .data 0 

circle_H_x:
    .data 0 

circle_H_y:
    .data 0 

# -----------
# - Sprites -
# -----------

sprite:
    .data 0
    
sprite_command:
    .data 0

sprite_pntr:
    .data 0

sprite_pntr_1:
    .data 0

sprite_collision:
    .data 0

sprite_tile:
    .data 0

sprite_x_offset:
    .data 0

sprite_y_offset:
    .data 0

sprite_x_pos:
    .data 0

sprite_x_pos_1:
    .data 0

sprite_y_pos:
    .data 0

sprite_y_pos_1:
    .data 0

sprite_hitbox_x_min:
    .data 0

sprite_hitbox_x_min_1:
    .data 0

sprite_hitbox_x_max:
    .data 0

sprite_hitbox_x_max_1:
    .data 0

sprite_hitbox_y_min:
    .data 0

sprite_hitbox_y_min_1:
    .data 0

sprite_hitbox_y_max:
    .data 0

sprite_hitbox_y_max_1:
    .data 0

sprite_limit_x_min:
    .data 0

sprite_limit_x_max:
    .data 0

sprite_limit_y_min:
    .data 0

sprite_limit_y_max:
    .data 0

sprite_edge:
    .data 0

sprite_number:
    .data 0

# -------------- 
# - Controller -
# --------------

rotary_switch:
	.data 0
	
fire_switch:
	.data 0
	
snes_switch:
	.data 0	

key:
    .data 0

# --------------- 
# - LCD Display -
# ---------------

lcd_delay_count:
	.data 0

lcd_pntr:
    .data 0

lcd_config:
    .data 0

# 0011 0011 Initialise
# 0011 0010 Initialise
# 0000 0110 Cursor move direction
# 0000 1100 Display On,Cursor Off, Blink Off
# 0010 1000 Data length, number of lines, font size
# 0000 0001 Clear display
# 1000 0000 LCD RAM address for the 1st line

init_string:
    .data 0x33
    .data 0x32
    .data 0x06
    .data 0x0C
    .data 0x28
    .data 0x01
    .data 0x80
    .data 0

message_string:
    .data 0x4F # O
    .data 0x58 # X
    .data 0x4F # O
    .data 0x20 # space
    .data 0x44 # D
    .data 0x65 # e
    .data 0x6D # m
    .data 0x6F # o
    .data 0

# --------- 
# - Maths -
# ---------

num:
    .data 0

randomNumberIndex:
    .data 0

randomNumber:
    .data 50

# -------- 
# - List -
# --------

listHeadPtr:
    .data 0

listTailPtr:
    .data 0

listIndex:
    .data 0

listAddr:
    .data 0

listData:
    .data 0

#>>

##################
# GAME VARIABLES #
##################

player_O_score:
	.data 0

player_X_score:
	.data 0

player:
    .data 0

position:
    .data 0

win:
    .data 0

finish:
    .data 0

restart:
    .data 0

player_O_try:
    .data 0

player_X_try:
    .data 0

grid_state:
    .data 0
    .data 0
    .data 0
    .data 0
    .data 0
    .data 0
    .data 0
    .data 0
    .data 0


# 64 random 0-8 values

random_O:
    .data 8
    .data 0
    .data 2
    .data 1
    .data 4
    .data 2
    .data 8
    .data 2
    .data 7
    .data 5
    .data 5
    .data 2
    .data 0
    .data 4
    .data 5
    .data 5
    .data 8
    .data 7
    .data 4
    .data 6
    .data 1
    .data 2
    .data 5
    .data 1
    .data 3
    .data 6
    .data 1
    .data 4
    .data 7
    .data 1
    .data 0
    .data 8
    .data 8
    .data 5
    .data 3
    .data 0
    .data 8
    .data 8
    .data 4
    .data 0
    .data 5
    .data 4
    .data 8
    .data 3
    .data 6
    .data 2
    .data 7
    .data 8
    .data 3
    .data 8
    .data 2
    .data 2
    .data 8
    .data 5
    .data 3
    .data 0
    .data 1
    .data 0
    .data 8
    .data 3
    .data 2
    .data 2
    .data 6
    .data 0

# 64 random 0-8 values

random_X:
    .data 6
    .data 7
    .data 6
    .data 6
    .data 8
    .data 5
    .data 2
    .data 2
    .data 6
    .data 6
    .data 0
    .data 0
    .data 4
    .data 5
    .data 8
    .data 4
    .data 7
    .data 4
    .data 4
    .data 2
    .data 5
    .data 1
    .data 6
    .data 6
    .data 8
    .data 2
    .data 8
    .data 8
    .data 1
    .data 6
    .data 2
    .data 6
    .data 0
    .data 8
    .data 6
    .data 2
    .data 0
    .data 3
    .data 2
    .data 1
    .data 0
    .data 4
    .data 8
    .data 2
    .data 3
    .data 0
    .data 8
    .data 3
    .data 0
    .data 0
    .data 5
    .data 6
    .data 3
    .data 4
    .data 5
    .data 0
    .data 2
    .data 2
    .data 6
    .data 0
    .data 1
    .data 0
    .data 8
    .data 3



















	



