DEV Community

Krinskumar Vaghasia
Krinskumar Vaghasia

Posted on

SPO Week 2.1 - lab

This week was was interesting and a little difficult. This is one of the hardest yet interesting courses I have taken in my school. The lab challenged us to make simple animations on the screen of 6502 emulator screen. Below is the started code for the lab 2.

;
; 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
Enter fullscreen mode Exit fullscreen mode

The started code moved this box on the screen diagonally. The square in the image below is actually moving.
Image description

New starting value

The first task was the have the box start moving diagonally starting from a new starting location. In the started code the box started moving from the top left corner of the screen. This task was rather simple cuz all we had to do was update the bytes where the x and y values were stored. My new version not only had a new starting position but the values of x and y were different as well.
Old Code

LDA #$00
STA XPOS
STA YPOS
Enter fullscreen mode Exit fullscreen mode

New Code

LDA #$02
STA XPOS
LDA #$09
STA YPOS
Enter fullscreen mode Exit fullscreen mode

Change the moving direction

After changing the spawn location, we were supposed to change the moving direction of the image. This was actually very easy, we just had to decrement the value of x and y instead of incrementing.
Old Code

INC XPOS
INC YPOS 
Enter fullscreen mode Exit fullscreen mode

New Code

INC XPOS
DEC YPOS 
Enter fullscreen mode Exit fullscreen mode

Bouncing Graphics

This was not as easy as changing a few lines of code. This was the most difficult part of this lab. I was a little intimidated by this part of the lab. This was challenging and I was not able to make this work. I had the idea of what the implementation would look like but because of my limited syntax knowledge I failed. The idea was to define boundaries for extremes and check if the next value of x could overflow the box. If that was true I would start decrementing if I was incrementing before and visa versa. This is the same for the y axis as well. I can however show you the code that I created while solving the problem.

LDX XPOS : load the value of x 
LDA XSTATE : tells us if we are adding or subtracting.
ADC XPOS : add/removes based on accumulater value.
CMP #$00
: reverse the direction of x
CMP #$1C
: reverse the direction of x

LDY YPOS : load the value of y 
LDA YSTATE : tells us if we are adding or subtracting.
ADC YPOS : add/removes based on accumulater value.
CMP #$00
: reverse the direction of y
CMP #$1C
: reverse the direction of y

Enter fullscreen mode Exit fullscreen mode

Reflection:

This lab broadened my perspective of the things that can be achieved using this language. I did not think that we would get this far with coding in such low level. We are literally doing animation now. This is so cool. Not only that but we can dynamically change the box into a x shape we would like. If we were to change the graphic each time it bounces, we would update a state somewhere when we reverse any direction as shown in the above code block. This lab was challenging for me, I just could not get the direction switch to work, maybe I am missing something. I will update you if I was able to get this done in my next blog of week 2!!.

Top comments (0)