Lab 2 - Lab Results
Introduction
In this blog post, I will share my experience working on a lab where we animated a small 5x5 graphic to move diagonally across the screen and bounce off the edges. The lab required an understanding of low-level memory manipulation, conditional logic, and efficient screen rendering. I'll walk you through the code, the changes made to implement bouncing logic, and my reflections on the learning process.
**Since we collaborated as a group on optimizing the code, my work may resemble that of my teammates
===================================================================
Initial Code
The following code moves a 5×5 graphic diagonally across the screen:
; ; 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 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=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 ; 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 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 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
Code example:
Code example:
Code example:
Code example:
; ; draw-image-subroutine.bouncing.6502 ; ; This routine places an arbitrary ; rectangular image on the screen at given ; coordinates and makes it bounce within ; the screen boundaries. ; ; 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 and bounces it off the edges ; Zero-page variables define XPOS $20 ; Current X position define YPOS $21 ; Current Y position define XINC $22 define YINC $23 START: LDA #$05 STA $12 STA $13 LDA #$0A STA XPOS LDA #$05 STA YPOS LDA #$01 STA XINC STA YINC MAINLOOP: LDA #<G_O STA $10 LDA #>G_O STA $11 LDA #$10 LDX XPOS LDY YPOS JSR DRAW LDY #$00 LDX #$50 DELAY: DEY BNE DELAY DEX BNE DELAY LDA #<G_BLANK STA $10 LDA #>G_BLANK STA $11 LDA #$10 LDX XPOS LDY YPOS JSR DRAW LDA XINC CMP #$01 BEQ INC_XPOS LDA XPOS SEC SBC #$01 STA XPOS JMP CHECK_X_BOUNDARY INC_XPOS: INC XPOS CHECK_X_BOUNDARY: LDA XPOS CMP #$1B BCC NO_CHANGE_X LDA #$FF STA XINC JMP UPDATE_Y NO_CHANGE_X: LDA XPOS CMP #$00 BNE UPDATE_Y LDA #$01 STA XINC UPDATE_Y: LDA YINC CMP #$01 BEQ INC_YPOS LDA YPOS SEC SBC #$01 STA YPOS JMP CHECK_Y_BOUNDARY INC_YPOS: INC YPOS CHECK_Y_BOUNDARY: LDA YPOS CMP #$1B BCC NO_CHANGE_Y LDA #$FF STA YINC JMP MAINLOOP NO_CHANGE_Y: LDA YPOS CMP #$00 BNE MAINLOOP LDA #$01 STA YINC JMP MAINLOOP ; ========================================== 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: STY SCRY STX SCRX TAY LDA $0000,Y STA IMGPTR LDA $0001,Y STA IMGPTRH LDA $0002,Y STA IMGWIDTH LDA $0003,Y STA IMGHEIGHT LDA #$00 STA SCRPTRH LDA SCRY STA SCRPTR LDY #$05 MULT: ASL SCRPTR ROL SCRPTRH DEY BNE MULT LDA SCRX CLC ADC SCRPTR STA SCRPTR LDA #$00 ADC SCRPTRH STA SCRPTRH LDA #$02 CLC ADC SCRPTRH STA SCRPTRH COPYROW: LDY #$00 ROWLOOP: LDA (IMGPTR),Y STA (SCRPTR),Y INY CPY IMGWIDTH BNE ROWLOOP LDA IMGWIDTH CLC ADC IMGPTR STA IMGPTR LDA #$00 ADC IMGPTRH STA IMGPTRH LDA #32 CLC ADC SCRPTR STA SCRPTR LDA #$00 ADC SCRPTRH STA SCRPTRH DEC IMGHEIGHT BNE COPYROW RTS ; ========================================== 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 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 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
==================================================================================Challenge Section Results
One of the challenges involved tweaking the delay loop to adjust the animation speed. A longer delay made movement smoother, while a shorter delay made it appear too fast or flickery. The balance was achieved with:
LDY #$00 LDX #$50 DELAY: DEY BNE DELAY DEX BNE DELAY
Additionally, another challenge was modifying the image to have different starting values for
XPOS
andYPOS
instead of (0,0), making it more visually dynamic. ConclusionThrough working on this lab, I gained a deeper understanding of advanced concepts like subroutines, loops, and jumps. I faced some difficulty grasping decimal values, as they are represented in hex in the 6502 system. While adding and subtracting values are straightforward in decimals, it took me some time to figure out how to implement them using memory addresses and hex notation.
Overall, the 6502 Math Lab has helped me think more in the 6502 language. While concepts like if/else, loops, and functions are easy to implement in languages I’m familiar with, such as JavaScript, it was fascinating to see how these logic structures are handled in a low-level language!
Comments
Post a Comment