Lab 2

 

6502 Math Lab


Introduction

This lab involved creating a diagonal-moving graphic in the 6502 emulator, ensuring the object bounces when it reaches the edges of the screen.

The provided code initializes a graphic on a bitmapped display and uses subroutines to animate it. The program also detects when the object reaches the screen's boundaries and reverses its direction accordingly. Here's a breakdown:

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


Initialization:

The graphic's starting position (XPOS and YPOS) and movement directions (XMVT and YMVT) are initialized.
A subroutine (DRAW) places the graphic on the screen.


Animation Logic:

  1. A loop moves the graphic diagonally by adjusting its XPOS and YPOS.
  2. The graphic is cleared after each step by overwriting it with a blank image.
  3. Boundary checks reverse movement direction upon collisions.


Bounce Logic:
Horizontal (XMVT) and vertical (YMVT) movements are adjusted dynamically to ensure the graphic bounces within the defined screen area.


Key Features

  1. Horizontal Movement:

    • The XMVT variable toggles between moving left (DEC XPOS) and right (INC XPOS) based on the object's position.

  2. Vertical Movement:

    • Similarly, YMVT toggles between moving up (DEC YPOS) and down (INC YPOS).
  3. Boundary Detection:

    • Horizontal boundaries: CMP XPOS with #$00 (left edge) and #$1B (right edge).
    • Vertical boundaries: CMP YPOS with #$00 (top edge) and #$1A (bottom edge).
  4. Dynamic Redrawing:

    • Each frame redraws the object and erases the previous one using the G_BLANK graphic.



Code Changes from Initial Instructions

Here are the key modifications to the initial code provided in the instructions:

  1. Movement Variables:

    • Added XMVT and YMVT to control horizontal and vertical movement directions.
    • Initialized XMVT and YMVT to #$00 (right/down initially).

    define XMVT $22 ; X movement define YMVT $23 ; Y movement LDA #$00 STA XMVT ; Moving right initially STA YMVT ; Moving down initially
  2. Boundary Detection and Direction Change:

    • Checked for collisions at the edges.
    • Reversed XMVT and YMVT when reaching the boundaries.
    ; Check for horizontal movement LDA XMVT BEQ HORIZONTAL_MOVEMENT DEC XPOS ; Moving left LDA XPOS CMP #$00 ; Check left edge BNE VERTICAL_MOVEMENT LDA #$00 ; Switch to moving right

    STA XMVT
    JMP VERICAL_MOVEMENT
    HORIZONTAL_MOVEMENT:
    INC XPOS 
    ; Moving right 
    LDA XPOS 
    CMP #27 
    ; Right edge 
    BNE VERTICAL_MOVEMENT 
    LDA #$01 ; Switch to moving left 
    STA XMVT

  3. Vertical Movement Logic

    • Similar to horizontal movement, reversed direction when hitting the top or bottom.
        VERTICAL_MOVEMENT:         LDA YMVT         BEQ MOVE_DOWN         DEC YPOS ; Moving up         LDA YPOS         CMP #$00 ; Top edge         BNE MAINLOOP         LDA #$00 ; Switch to moving down         STA YMVT         JMP MAINLOOP                  MOVE_DOWN:         INC YPOS ; Moving down         LDA YPOS         CMP #26 ; Bottom edge         BNE MAINLOOP         LDA #$01 ; Switch to moving up         STA YMVT
  1. Erasing and Redrawing the Graphic:
    • Used G_BLANK to clear the previous position before moving the graphic.


Comments

Popular posts from this blog

Building GCC Part 2

Wrapping Up Project : Stage 3