Lab3 Overview
This lab is to prepare for learning more complex x86_64 and AArch64 assembly language, by writing code with arithmetic/math in 6502 assembly language.
The option I chose is bouncing graphic. It requires several techniques, including placing a graphic on the screen, bouncing an object around the screen and detecting when the object has collided with the edge of the screen or other objects.
At this stage, the most important part is to improve the draw
function, make this function works well when the ball is moving, get cleared then redrawed. Especially the taking keystroke input
functionality, it took a lot of time to write and after all, keystrokes other than up, down, left, right arrow keys can pause the ball from moving. Thus, this function is not fully working as designed.
The code was shown below, including functions to calculate pointer location, draw graphic, taking and check keystrokes, check if the ball touching the edge of the screen, clear the screen for redraw the ball:
define WIDTH 5
define HEIGHT 5
define POINTER $12
define POINTER_H $13
define ROW_COUNT $14
define ROW $15
define COLUMN $16
define CHECK_LINE $17 ; this is to check the edge
define ROW_FLAG $18 ; edge on row or col flag
define COL_FLAG $19
define PTR_CAL $20
define DATA_INDEX $21
define SCREENCOL_INDEX $22
define KEY $23
lda #$00
sta ROW_FLAG
sta COL_FLAG
lda #$05
sta ROW
lda #$05
sta COLUMN
; prepare to move by row and col
cal_init:
lda #$00
sta POINTER
lda #$02
sta POINTER_H
lda #$00
sta ROW_COUNT
lda #$00
sta PTR_CAL
cmp ROW
beq column_count
bne row_count
row_count:
lda PTR_CAL
clc
adc #$20
sta PTR_CAL
lda POINTER_H
adc #$00
sta POINTER_H
inc ROW_COUNT
lda ROW
cmp ROW_COUNT
bne row_count ; run utill get the row set
beq column_count
column_count:
lda PTR_CAL
clc
adc COLUMN
sta PTR_CAL
sta POINTER ; once row and col done, set pointer
; draw graphic initializing
lda #$00
sta ROW_COUNT
ldx #$00
ldy #$00
; draw graph, while checking the keystroke
draw: lda ball,x
sta (POINTER),y
inx
iny
cpy #WIDTH
bne draw
inc ROW_COUNT
lda #HEIGHT
cmp ROW_COUNT
beq readkey_init
lda POINTER
clc
adc #$20
sta POINTER
lda POINTER_H
adc #$00
sta POINTER_H
ldy #$00
beq draw
;
readkey_init:
txa
sta DATA_INDEX
tya
sta SCREENCOL_INDEX
readkey: lda $ff ; get a keystroke
ldx #$00 ; clear out the key buffer
stx $ff ; store index x in memory
cmp #$80 ; if not a cursor key, ignore
bmi readkey_check ; branch on minus
cmp #$84
bpl readkey_check ; branch on plus
cmp #$80 ; check key, up key
bne rightKey_check
dec ROW ; if yes, decrement row
jmp readkey_check
rightKey_check:
cmp #$81 ; check key, right key
bne downKey_check
inc COLUMN ; if yes, increment col
jmp readkey_check
downKey_check:
cmp #$82 ; check if key, down key
bne leftKey_check
inc ROW ; if yes, increment row
jmp readkey_check
leftKey_check:
cmp #$83 ; check if key, left key
bne readkey_check
dec COLUMN ; if yes, decrement col
clc
bcc readkey_check
readkey_check:
ldx DATA_INDEX
ldy SCREENCOL_INDEX
jmp check_location
check_location:
jsr check_top
jsr check_bottom
jsr check_right
jsr check_left
jsr move_pointer
check_initialize:
lda #$00
sta CHECK_LINE
rts ; return
check_top:
jsr check_initialize
lda ROW
cmp #$01 ; 01
lda CHECK_LINE
adc #$00
cmp #$00
beq flip_rowFlag
rts
check_bottom:
jsr check_initialize
lda ROW
cmp #$1b ; 1b
lda CHECK_LINE
adc #$00
cmp #$01
beq flip_rowFlag
rts
check_left:
jsr check_initialize
lda COLUMN
cmp #$01 ; 01
lda CHECK_LINE
adc #$00
cmp #$00
beq flip_colFlag
rts
check_right:
jsr check_initialize
lda COLUMN
cmp #$1b
lda CHECK_LINE
adc #$00
cmp #$01
beq flip_colFlag
rts
;Set Row Flag
flip_rowFlag:
lda ROW_FLAG
cmp #$00
beq inc_rowFlag
bne dec_rowFlag
rts
inc_rowFlag:
inc ROW_FLAG
rts
dec_rowFlag:
dec ROW_FLAG
rts
; Set Col Flag
flip_colFlag:
lda COLFLIP_FLAG
cmp #$00
beq inc_colFlag
bne dec_colFlag
rts
inc_colFlag:
inc COLFLIP_FLAG
rts
dec_colFlag:
dec COLFLIP_FLAG
rts
; move the graph
; first move the pointer
move_pointer:
jsr row_check
jsr col_check
jmp clear ; jump to clear
row_check:
lda ROW_FLAG
cmp #$01
beq dec_row
bne inc_row
col_check:
lda COLFLIP_FLAG
cmp #$01
beq dec_col
bne inc_col
inc_row:
inc ROW
rts
dec_row:
dec ROW
rts
inc_col:
inc COLUMN
rts
dec_col:
dec COLUMN
rts
; move the graph
;move: inc ROW
; inc COLUMN
; clear the screen before redraw the graph
clear: lda ball
sta POINTER
lda #$02
sta POINTER_H
ldy #$00
tya
clear_loop:
sta (POINTER),y
iny
bne clear_loop
inc POINTER_H
ldx POINTER_H
cpx #$06
bne clear_loop
jsr cal_init
; data constant byte (dcb)
ball:
dcb 00,07,07,07,00
dcb 07,07,07,07,07
dcb 07,07,07,07,07
dcb 07,07,07,07,07
dcb 00,07,07,07,00
what I have learnt
The main take away is to use branches, functions and subroutines to properly put all functionalities work together. The second most important stuff is the math (addition) in 6502 assembly language, especially with carry.
All work on this lab can be found by, part I, part II, and this part. It took me a lot of time trying to think in the way properly to program using assembly language. I think I still need more time to be more proficient in branching and subroutines in assembly language.
Top comments (0)