SPO600 Lab2 (Pt.3)-- challenges 3 & 4 and reflection
SPO600 Lab2 (Pt.3)-- challenges 3 & 4 and reflection
Subsequence to part1 and part2, I am revising a 6502 instruction assembly program which allows a logo to bounce within the screen.
Challenges
Lets work on Challenges 3 and 4.
1. Permit integer value other than -1 and +1 for the X and Y increments (logo velocity).
2. Permit fractional value for the X and Y increments (eg. +1.5 or -0.75)
3. Perturb the ball's position or velocity
4. Change the graphic image or colour each time it bounces
Problems analysis and solutions
Assumption:
1. Only velocity of the bounce direction will be changed.
2. the logo is allowed to stop in case the ball velocity changed to 0 due to the perturbing. (unlikely happening)
3. We do not do perturb to the position since it is just similar to that of velocity.
Solution:
Simple add a Perturb subroutine so that we can add perturbing when it bounds.
code:
; 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:" ; Zero-page variables define XPOSL $20 define XPOSH $21 define YPOSL $22 define YPOSH $23 define XNEXTL $24 define XNEXTH $25 define YNEXTL $26 define YNEXTH $27 define X_VL $28 define X_VH $29 define Y_VL $2A define Y_VH $2B START: ; Set up the width and height elements of the data structure LDA #$05 STA $12 ; IMAGE WIDTH STA $13 ; IMAGE HEIGHT ; initial position LDA #$00 STA XPOSL LDA #$01 STA XPOSH LDA #$00 STA YPOSL LDA #$03 STA YPOSH ; initial velocity x = 1.5, y =-0.75 LDA #$01 STA X_VH LDA #$80 STA X_VL LDA #$40 STA Y_VL LDA #$ff STA Y_VH ; 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_X STA $10 LDA #>G_X STA $11 ; Place the image on the screen LDA #$10 ; Address in zeropage of the data structure LDX XPOSH ; X position LDY YPOSH ; 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 XPOSH LDY YPOSH JSR DRAW JMP MOVE TEMP: JMP MAINLOOP ; Increment the predicted position MOVE: LDA X_VL CLC ADC XPOSL STA XNEXTL LDA X_VH ADC XPOSH STA XNEXTH LDA Y_VL CLC ADC YPOSL STA YNEXTL LDA Y_VH ADC YPOSH STA YNEXTH X_LEFTCHECK: ;check if X reach left edge LDA XNEXTH BMI X_BOUNCE_L ;check if X excess right edge LDA XNEXTH CMP #$1b BCS X_BOUNCE_R JMP Y_TOPCHECK X_BOUNCE_R: ;bounce on right edge LDA #$00 SEC SBC X_VL STA X_VL LDA #$00 SBC X_VH STA X_VH LDA XNEXTH SEC SBC #$1b STA XNEXTH LDA $00 SEC SBC XNEXTL STA XNEXTL LDA #$1b SBC XNEXTH STA XNEXTH JMP X_PERTURB X_BOUNCE_L: ;bounce on left edge LDA #$00 SEC SBC X_VL STA X_VL LDA #$00 SBC X_VH STA X_VH LDA #$00 SEC SBC XNEXTL STA XNEXTL LDA #$00 SBC XNEXTH STA XNEXTH X_PERTURB:; add random velocity in x direction lda $fe CLC ADC X_VL STA X_VL LDA #$00 ADC X_VH STA X_VH ;check if Y reach TOP edge Y_TOPCHECK: LDA YNEXTH BMI Y_BOUNCE_T ;check if Y reach Bottom edge Y_BOTCHECK: LDA YNEXTH CMP #$1b BCS Y_BOUNCE_B JMP END_CHECK Y_BOUNCE_T: LDA #$00 ;reverse velocity SEC SBC Y_VL STA Y_VL LDA #$00 SBC Y_VH STA Y_VH ;reverse position LDA #$00 SEC SBC YNEXTL STA YNEXTL LDA #$00 SBC YNEXTH STA YNEXTH JMP Y_PERTURB Y_BOUNCE_B: LDA #$00 SEC SBC Y_VL STA Y_VL LDA #$00 SBC Y_VH STA Y_VH LDA YNEXTH SEC SBC #$1b STA YNEXTH LDA $00 SEC SBC YNEXTL STA YNEXTL LDA #$1b SBC YNEXTH STA YNEXTH Y_PERTURB:; add random velocity in y direction lda $fe CLC ADC Y_VL STA Y_VL LDA #$00 ADC Y_VH STA Y_VH END_CHECK: LDA XNEXTH STA XPOSH LDA XNEXTL STA XPOSL LDA YNEXTH STA YPOSH LDA YNEXTL STA YPOSL JMP TEMP ; Repeat infinitely ; ========================================== ; ; 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
The highlighted part is the perturb part for the velocity change.
Output:
Challenges 4
Change the graphic image each time it bounces
Solution:
Use two 2-bytes pointer to store the location of the logos. Use a Subroutine to swap pointer when ever it bounces.
; 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:" ; Zero-page variables define XPOSL $20 define XPOSH $21 define YPOSL $22 define YPOSH $23 define XNEXTL $24 define XNEXTH $25 define YNEXTL $26 define YNEXTH $27 define X_VL $28 define X_VH $29 define Y_VL $2A define Y_VH $2B define LOGO_AL $30 define LOGO_AH $31 define LOGO_BL $32 define LOGO_BH $33 START: ; Set up the width and height elements of the data structure LDA #$05 STA $12 ; IMAGE WIDTH STA $13 ; IMAGE HEIGHT ; initi logo attribute LDA #<G_O STA LOGO_AL LDA #>G_O STA LOGO_AH LDA #<G_X STA LOGO_BL LDA #>G_X STA LOGO_BH ; initial position LDA #$00 STA XPOSL LDA #$01 STA XPOSH LDA #$00 STA YPOSL LDA #$03 STA YPOSH ; initial velocity x = 1.5, y =-0.75 LDA #$01 STA X_VH LDA #$80 STA X_VL LDA #$40 STA Y_VL LDA #$ff STA Y_VH ; 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 ; Main loop for diagonal animation MAINLOOP: LDA LOGO_AL STA $10 LDA LOGO_AH STA $11 ; Place the image on the screen LDA #$10 ; Address in zeropage of the data structure LDX XPOSH ; X position LDY YPOSH ; 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 XPOSH LDY YPOSH JSR DRAW JMP MOVE TEMP: JMP MAINLOOP ; Increment the predicted position MOVE: LDA X_VL CLC ADC XPOSL STA XNEXTL LDA X_VH ADC XPOSH STA XNEXTH LDA Y_VL CLC ADC YPOSL STA YNEXTL LDA Y_VH ADC YPOSH STA YNEXTH X_LEFTCHECK: ;check if X reach left edge LDA XNEXTH BMI X_BOUNCE_L ;check if X excess right edge LDA XNEXTH CMP #$1b BCS X_BOUNCE_R JMP Y_TOPCHECK X_BOUNCE_R: ;bounce on right edge LDA #$00 SEC SBC X_VL STA X_VL LDA #$00 SBC X_VH STA X_VH LDA XNEXTH SEC SBC #$1b STA XNEXTH LDA $00 SEC SBC XNEXTL STA XNEXTL LDA #$1b SBC XNEXTH STA XNEXTH JSR CH_LOGO JMP Y_TOPCHECK X_BOUNCE_L: ;bounce on left edge LDA #$00 SEC SBC X_VL STA X_VL LDA #$00 SBC X_VH STA X_VH LDA #$00 SEC SBC XNEXTL STA XNEXTL LDA #$00 SBC XNEXTH STA XNEXTH JSR CH_LOGO ;check if Y reach TOP edge Y_TOPCHECK: LDA YNEXTH BMI Y_BOUNCE_T ;check if Y reach Bottom edge Y_BOTCHECK: LDA YNEXTH CMP #$1b BCS Y_BOUNCE_B JMP END_CHECK Y_BOUNCE_T: LDA #$00 ;reverse velocity SEC SBC Y_VL STA Y_VL LDA #$00 SBC Y_VH STA Y_VH ;reverse position LDA #$00 SEC SBC YNEXTL STA YNEXTL LDA #$00 SBC YNEXTH STA YNEXTH JSR CH_LOGO JMP END_CHECK Y_BOUNCE_B: LDA #$00 SEC SBC Y_VL STA Y_VL LDA #$00 SBC Y_VH STA Y_VH LDA YNEXTH SEC SBC #$1b STA YNEXTH LDA $00 SEC SBC YNEXTL STA YNEXTL LDA #$1b SBC YNEXTH STA YNEXTH JSR CH_LOGO JMP END_CHECK CH_LOGO:; add random velocity in y direction LDA LOGO_AL LDY LOGO_BL STA LOGO_BL STY LOGO_AL LDA LOGO_AH LDY LOGO_BH STA LOGO_BH STY LOGO_AH RTS END_CHECK: LDA XNEXTH STA XPOSH LDA XNEXTL STA XPOSL LDA YNEXTH STA YPOSH LDA YNEXTL STA YPOSL JMP TEMP ; Repeat infinitely ; ========================================== ; ; 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
yellow highlighted part is the declaration and initialization of the two logo pointer
Cyan highlighted part is the subroutine of the swapping of two logo pointer
Output:
Reflection
In this workshop, I practiced subtraction and addition of multi-bytes values. I noted the role of the carry flag in these operation. Meanwhile, I learn that CMP is actually perform subtraction without recording the result. However, negative flag, carry flag and zero flag will indicate the result of the subtraction. In this connection, we are able to use CMP instruction to perform some conditional branching, eg BNE, BCC, BMI, etc. Also, I practiced to use JSR, JMP and RTS to do subroutine.
Regarding assembly language, I am happy that I know what exactly would happen when a instruction run. However, I feel like even a simple task in assembly language is extremely time consuming. Also, assembly code, with multiple JMP, RTS,JSR is hard to read.
Comments
Post a Comment