Lab 2 - 6502 Math Lab

For the "Bouncing Graphic"

1. Introduction:

It is the advanced version that implement four parts to make the graphic bounce when it hits the edge of the bitmapped.

The basic version was making the graphic(A dot or a circle) from A point moves to B point and re-run it again.
Therefore, the advanced version is making the graphic moves from left to right or bottom to top, or from right to left or from top to bottom.

2. Coding

The following code is about this assembly program:
;
; draw-image-subroutine.6502
;
; This is a routine that can place an arbitrary 
; rectangular image on to the screen at given
; coordinates.
;
; Chris Tyler made on 2024-09-17 
; Licensed under GPLv2+
;

;
; The subroutine is below starting at the 
; label "DRAW:"
;

; Test code for our subroutine
; Moves an image diagonally across the screen

; Zero-page variables
define XPOS $20
define YPOS $21
define XINC $22
define YINC $23


START:

; Set up the width and height elements of the data structure
  LDA #$05
  STA $12       ; IMAGE WIDTH
  STA $13       ; IMAGE HEIGHT

; Set initial position X=10 Y=15
  LDA #$0A
  STA XPOS
  LDA #$0F
  STA YPOS

; Set initial increments
  LDA #$01
  STA XINC
  LDA #$FF      ; -1 in two's complement
  STA YINC

; Main loop for diagonal animation
MAINLOOP:

  ; Set pointer to the image
  ; Use G_O or G_X as desired
  ; The syntax #<LABEL returns the low byte of LABEL
  ; The syntax #>LABEL returns the high byte of LABEL

  LDA #<G_O
  STA $10
  LDA #>G_O
  STA $11

  ; Place the image on the screen
  LDA #$10  ; Address in zeropage of the data structure
  LDX XPOS  ; X position
  LDY YPOS  ; Y position
  JSR DRAW  ; Call the subroutine

  ; Delay
  JSR DELAY

  ; Clear the old image
  LDA #<G_BLANK
  STA $10
  LDA #>G_BLANK
  STA $11
  LDA #$10
  LDX XPOS
  LDY YPOS
  JSR DRAW

  ; Update position
  CLC
  LDA XPOS
  ADC XINC
  STA XPOS

  CLC
  LDA YPOS
  ADC YINC
  STA YPOS

  ; Check for horizontal bounds
  LDA XPOS
  CMP #$00
  BEQ BOUNCE_X
  CMP #$1B      ; 32 - 5 (image width)
  BEQ BOUNCE_X
  JMP CHECK_Y

BOUNCE_X:
  LDA XINC
  EOR #$FF      ; Flip all bits
  CLC
  ADC #$01      ; Add 1 to get two's complement
  STA XINC

CHECK_Y:
  LDA YPOS
  CMP #$00
  BEQ BOUNCE_Y
  CMP #$1B      ; 32 - 5 (image height)
  BEQ BOUNCE_Y
  JMP CONTINUE

BOUNCE_Y:
  LDA YINC
  EOR #$FF
  CLC
  ADC #$01
  STA YINC

CONTINUE:
  JMP MAINLOOP

DELAY:
  ; Delay to show the image
  LDY #$00
  LDX #$50
DELAY_LOOP:
  DEY
  BNE DELAY_LOOP
  DEX
  BNE DELAY_LOOP
  RTS

  ; Continue for 29 frames of animation
  LDA #28
  CMP XPOS
  BNE MAINLOOP

  ; Repeat infinitely
  JMP START

; ==========================================
;
; DRAW :: Subroutine to draw an image on 
;         the bitmapped display
;
; Entry conditions:
;    A - location in zero page of: 
;        a pointer to the image (2 bytes)
;        followed by the image width (1 byte)
;        followed by the image height (1 byte)
;    X - horizontal location to put the image
;    Y - vertical location to put the image
;
; Exit conditions:
;    All registers are undefined
;
; Zero-page memory locations
define IMGPTR    $A0
define IMGPTRH   $A1
define IMGWIDTH  $A2
define IMGHEIGHT $A3
define SCRPTR    $A4
define SCRPTRH   $A5
define SCRX      $A6
define SCRY      $A7

DRAW:
  ; SAVE THE X AND Y REG VALUES
  STY SCRY
  STX SCRX

  ; GET THE DATA STRUCTURE
  TAY
  LDA $0000,Y
  STA IMGPTR
  LDA $0001,Y
  STA IMGPTRH
  LDA $0002,Y
  STA IMGWIDTH
  LDA $0003,Y
  STA IMGHEIGHT

  ; CALCULATE THE START OF THE IMAGE ON
  ; SCREEN AND PLACE IN SCRPTRH
  ;
  ; THIS IS $0200 (START OF SCREEN) +
  ; SCRX + SCRY * 32
  ; 
  ; WE'LL DO THE MULTIPLICATION FIRST
  ; START BY PLACING SCRY INTO SCRPTR
  LDA #$00
  STA SCRPTRH
  LDA SCRY
  STA SCRPTR
  ; NOW DO 5 LEFT SHIFTS TO MULTIPLY BY 32
  LDY #$05     ; NUMBER OF SHIFTS
MULT:
  ASL SCRPTR   ; PERFORM 16-BIT LEFT SHIFT
  ROL SCRPTRH
  DEY
  BNE MULT

  ; NOW ADD THE X VALUE
  LDA SCRX
  CLC
  ADC SCRPTR
  STA SCRPTR
  LDA #$00
  ADC SCRPTRH
  STA SCRPTRH

  ; NOW ADD THE SCREEN BASE ADDRESS OF $0200
  ; SINCE THE LOW BYTE IS $00 WE CAN IGNORE IT
  LDA #$02
  CLC
  ADC SCRPTRH
  STA SCRPTRH
  ; NOTE WE COULD HAVE DONE TWO: INC SCRPTRH

  ; NOW WE HAVE A POINTER TO THE IMAGE IN MEM
  ; COPY A ROW OF IMAGE DATA
COPYROW:
  LDY #$00
ROWLOOP:
  LDA (IMGPTR),Y
  STA (SCRPTR),Y
  INY
  CPY IMGWIDTH
  BNE ROWLOOP

  ; NOW WE NEED TO ADVANCE TO THE NEXT ROW
  ; ADD IMGWIDTH TO THE IMGPTR
  LDA IMGWIDTH
  CLC
  ADC IMGPTR
  STA IMGPTR
  LDA #$00
  ADC IMGPTRH
  STA IMGPTRH
 
  ; ADD 32 TO THE SCRPTR
  LDA #32
  CLC
  ADC SCRPTR
  STA SCRPTR
  LDA #$00
  ADC SCRPTRH
  STA SCRPTRH

  ; DECREMENT THE LINE COUNT AND SEE IF WE'RE
  ; DONE
  DEC IMGHEIGHT
  BNE COPYROW

  RTS

; ==========================================

; 5x5 pixel images

; Image of a blue "O" on black background
G_O:
DCB $00,$0e,$0e,$0e,$00
DCB $0e,$00,$00,$00,$0e
DCB $0e,$00,$00,$00,$0e
DCB $0e,$00,$00,$00,$0e
DCB $00,$0e,$0e,$0e,$00

; Image of a yellow "X" on a black background
G_X:
DCB $07,$00,$00,$00,$07
DCB $00,$07,$00,$07,$00
DCB $00,$00,$07,$00,$00
DCB $00,$07,$00,$07,$00
DCB $07,$00,$00,$00,$07

; Image of a black square
G_BLANK:
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00



3. Describe

To make the graphic bounce when it hits the edge of the bitmapped by the following four parts:

1.
  ; Update position
  CLC
  LDA XPOS
  ADC XINC
  STA XPOS

  CLC
  LDA YPOS
  ADC YINC
  STA YPOS

  ; Check for horizontal bounds
  LDA XPOS
  CMP #$00
  BEQ BOUNCE_X
  CMP #$1B      ; 32 - 5 (image width)
  BEQ BOUNCE_X
  JMP CHECK_Y

2.
BOUNCE_X:
  LDA XINC
  EOR #$FF      ; Flip all bits
  CLC
  ADC #$01      ; Add 1 to get two's complement
  STA XINC

3.
CHECK_Y:
  LDA YPOS
  CMP #$00
  BEQ BOUNCE_Y
  CMP #$1B      ; 32 - 5 (image height)
  BEQ BOUNCE_Y
  JMP CONTINUE

4.
BOUNCE_Y:
  LDA YINC
  EOR #$FF
  CLC
  ADC #$01
  STA YINC


4. Reflection

The first part is about checking the XPOS which means does graphic hits the horizontal bounds and to update the position of the graphic.

The second part is for after the graphic was hit the horizontal bounds and flip the bits by add 1 to change the movement.

The third part is the opposite of the first part that checking the YPOS hits the vertical bounds and to call the fourth part.

The fourth part is almost the same as the second part and flip the bits by add 1 to move the graphic as well.

From this lab I learned something like in the modern programming languages that I wanted to compare and I would use IF-ELSE statement; however, in assembly language that I could just use CMP and Hexadecimal instead IF-ELSE.

留言