Lab 02

Lab 02 

Description

This post is about Lab 02 for SPO600 course at Seneca College.

In this Lab, the students are given a code that darw a O image on bitmap, which currently moves diagonally. The task of the students is making the O image bounce off permanently when it hits a wall.

The code below is given to the students.

;
; draw-image-subroutine.6502
;
; This is a routine that can place an arbitrary 
; rectangular image on to the screen at given
; coordinates.
;
; Chris Tyler 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

; Set up the data structure
; The syntax #<LABEL returns the low byte of LABEL
; The syntax #>LABEL returns the high byte of LABEL
LDA #<G_X     ; POINTER TO GRAPHIC
STA $10
LDA #>G_X
STA $11
LDA #$05
STA $12       ; IMAGE WIDTH
STA $13       ; IMAGE HEIGHT

; Set initial position X=Y=0
LDA #$00
STA XPOS
STA YPOS

; Main loop for diagonal animation
MAINLOOP:

  ; Set pointer to the image
  ; Use G_O or G_X as desired
  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 to show the image
  LDY #$00
  LDX #$50
DELAY:
  DEY
  BNE DELAY
  DEX
  BNE DELAY

  ; Set pointer to the blank graphic
  LDA #<G_BLANK
  STA $10
  LDA #>G_BLANK
  STA $11

  ; Draw the blank graphic to clear the old image
  LDA #$10 ; LOCATION OF DATA STRUCTURE
  LDX XPOS
  LDY YPOS
  JSR DRAW

  ; Increment the position
  INC XPOS
  INC YPOS

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

  ; Repeat infinitely
  JMP $0600

; ==========================================
;
; 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

Since the Code is too long and the parts I need to change is the MAINLOOP, I will only write about the code in LOOP.

1. Changing the first location of  "O" image.

; Set initial position X=Y=0
LDA #$0d ; X position to Middle
STA XPOS
LDA #$00 ; Y position to First Row
STA YPOS
First, I changed the start locating into the middle of the first row with the code above.


2. Changing the moving direction.
  ; Increment the position
  DEC XPOS ; Image moving left by decreasing X position
  INC YPOS
I changed the moving direction of the image to the left.


3. Chaning Branching Condition

  ; Continue for 29 frames of animation
  LDA XPOS     ; Load current X Position
  CMP #00.     ; Compare if it becomes 0
  BNE MAINLOOP ; Otherwise, Go back to MAINLOOP    
I changed the branching condition. If the current X position becomes 0, it goes to the next code.


4. Making Second Loop for bouncing off from the left wall toward down and right direction


SECONDLOOP:
  ; Set pointer to the image
  ; Use G_O or G_X as desired
  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 to show the image
  LDY #$00
  LDX #$50
DELAY2:    ; Becareful for changing the TAG name 
  DEY      ; Otherwise you go back to the MAINLOOP
  BNE DELAY2
  DEX
  BNE DELAY2

  ; Set pointer to the blank graphic
  LDA #<G_BLANK
  STA $10
  LDA #>G_BLANK
  STA $11
 
  ; Draw the blank graphic to clear the old image
  LDA #$10 ; LOCATION OF DATA STRUCTURE
  LDX XPOS
  LDY YPOS
  JSR DRAW

  ; Increment the position
  INC XPOS ; Move the image toward the right
  INC YPOS ; Move the image toward the bottom

  LDA $fe  ; this is a debugging code to check if this loop is being executed
  STA $0310

  ; Continue for 29 frames of animation
  LDA #28  ; Set the Accumulator with 28
  CMP YPOS ; If Y position becomes 28, Move to the next Code
  BNE SECONDLOOP

The SECONDLoop is basically the same as MAINLOOP except for moving direction and branching condition.


5. Making a THIRDLOOP for bouncing off from the bottom wall toward up and right direciton

  THIRDLOOP:
  ; Set pointer to the image
  ; Use G_O or G_X as desired
  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 to show the image
  LDY #$00
  LDX #$50
DELAY3: ; Becareful for changing the TAG name 
  DEY   ; Otherwise you go back to the MAINLOOP
  BNE DELAY3
  DEX
  BNE DELAY3

  ; Set pointer to the blank graphic
  LDA #<G_BLANK
  STA $10
  LDA #>G_BLANK
  STA $11
 
  ; Draw the blank graphic to clear the old image
  LDA #$10 ; LOCATION OF DATA STRUCTURE
  LDX XPOS
  LDY YPOS
  JSR DRAW

  ; Increment the position
  INC XPOS ; Move the image toward the right
  DEC YPOS ; Move the image toward the Top

  LDA $fe  ; this is a debugging code to check if this loop is being executed
  STA $0410

  ; Check branching condition for Loop
  LDA #28  ; Set the Accumulator with 28
  CMP XPOS ; If X position becomes 28, Move toward left
  BNE THIRDLOOP

THIRDLOOP is also almost same as the other loops except for moving direction and branching condition.


6. Making Fourth Loop for bouncing off from the right wall toward up and left direction, and then going back to MAINLOOP

FOURTHLOOP:
  ; Set pointer to the image
  ; Use G_O or G_X as desired
  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 to show the image
  LDY #$00
  LDX #$50
DELAY4:      ; Becareful for changing the TAG name 
  DEY        ; Otherwise you go back to the MAINLOOP
  BNE DELAY4
  DEX
  BNE DELAY4

  ; Set pointer to the blank graphic
  LDA #<G_BLANK
  STA $10
  LDA #>G_BLANK
  STA $11
 
  ; Draw the blank graphic to clear the old image
  LDA #$10 ; LOCATION OF DATA STRUCTURE
  LDX XPOS
  LDY YPOS
  JSR DRAW

  ; Increment the position
  DEC XPOS ; Moving Left
  DEC YPOS ; Moving Upward

  LDA $fe  ; this is a debugging code to check if this loop is being executed
  STA $0510

  ; Check branching condition for Loop
  LDA YPOS ; Load the accumulator with current Y position
  CMP #00  ; Compare if it becomes Zero, Otherwise Goes back to FOURTHLOOP
  BNE FOURTHLOOP

JMP MAINLOOP ; When the FOURTHLOOP is finished, it goes back to the MAINLOOP

Reflection
This lab was extremely challenging. I still don't understand how it draws the image. There were some mistakes that I made that made me frustrated. First, I copied MAINLOOP and changed it into SECONDLOOP. However, I didn't understand why the SECONDLOOP is not executed. It only worked once and then went back to MAINLOOP. The cause of this problem was that I didn't chnage the DELAY tag, so it went back to the DELAY located in MAINLOOP. Chaning the moving direction of the image was not very difficult; however, the drawing logic and making branching and jumping was a little bit confusing. I had to be very careful of setting the condition and TAG name. From this Lab, I learned how to use Branches and Jump and how to set the condition for Branch instructions(BNE, BEQ, ...) such as using CMP or zero flags. 



Comments

popular posts in this blog

Project Stage 2 - part 2 : Clone-Pruning Analysis Pass

Project Stage 2 part 4 - Testing clone-test-core.c file with Modified GCC file and making further modification

Project Stage 2 part 3 - Compile a program with revised GCC