Firstly on the overflow flag, I realise now I shouldn't have been using it. Now I learn that is only used with BVC when you are working with a signed number. I should have been checking the carry flag instead.
Satpro you also pulled me up on how I was storing the CPU register. There was no need to double it up to a memory address too! I see now that as long as the stack is used properly, you can pull it back off again at the right time.
Anyway, I now have kind of what I wanted. A small program to test idea of using double precision to control speed of a sprite. It needs a lot of work to be more than this of course. But I play with one idea at a time until I think I've grasped it.
Here is my entire code, written for ACME in C64 Studio. BTW conv2dec is a routine to output the value of sprite0yprecision to screen. which helped me debug what was going wrong. The movement speed of the sprite down the screen can be controlled by changing the value of sprite0speed, currently set to $ff (fastest speed).
Any comments welcome.
Code: Select all
!to "doublePrecision.prg",cbm bordercolor = $d020 backgroundcolor = $d021 interruptcontrol = $d01a interruptroutineaddress1 = $0314 interruptroutineaddress2 = $0315 rasterline = $d012 spriteonoff = $d015 spritemode = $d01c spritepointer0 = $07f8 spritecolor1 = $d025 spritecolor2 = $d026 sprite0color = $d027 sprite0xpos = $d000 sprite0ypos = $d001 sprite0ybuffer = $c000 frameReadyFlag = $c001 sprite0speed = $ff sprite0yPrecision = $c002 sprite0yPrecision2 = $c003 div_lo = $c005 div_hi = $c006 *= $0801 !byte $0d,$08,$00,$01,$9e,$20,$34,$30,$39,$36,$00,$00,$00 ; Types the basic program SYS 4096 into memory for more convenient running *= $1000 lda #$00 sta frameReadyFlag lda #$0B ; Set foreground and border colour to dark grey sta bordercolor sta backgroundcolor lda #$93 ; Clear the screen by loading clear screen character and then calling a kernel routine jsr $ffd2 lda #$00 ; Load black into first shared sprite colour sta spritecolor1 lda #$01 ; Load white into second shared sprite colour sta spritecolor2 lda #$05 ; Load green into sprite 0 unique colour sta sprite0color lda #$80 ; Load first sprite pointer to point at $2000 ($2000 / $40 = $80) sta spritepointer0 ; The VIC-IIs default memory address for sprite pointer 0 lda #$01 ; Enable sprite 0 by turning on first bit of $d015 sta spriteonoff sta spritemode ; Set sprite 0 to multicolor mode lda #$96 ; Load coordinates to place sprite (in this case W150,H150) sta sprite0xpos sta sprite0ypos sei ; Disable the CPU responding to interrupts lda #$7f ; Keep some other random interrupts off sta $dc0d sta $dd0d lda $dc0d ; Acknowledge any CIA 1 interrupts lda $dd0d ; Acknowledge any CIA 2 interrupts lda #$01 ; Turn on VIC raster interrupts sta interruptcontrol lda #$fa ; Generate interrupt on line fa sta rasterline lda #$1b ;Not sure what this does exactly? sta $d011 lda #<spriteControl ;set the correct address for the interrupt routine sta interruptroutineaddress1 lda #>spriteControl sta interruptroutineaddress2 cli ; turn all interrupts back on mainLoop lda #sprite0speed ; get the sprite speed and add it to the precision buffer clc adc sprite0yPrecision sta sprite0yPrecision php jsr conv2dec plp bcc mainLoop ; loop again if didn't overflow lda #$08 ; we did carry so add eight to the next buffer clc adc sprite0yPrecision2 sta sprite0yPrecision2 bcc mainLoop ; loop again if didnâ€™t over flow lda #$01 clc adc sprite0ybuffer sta sprite0ybuffer inc bordercolor jmp mainLoop ; Sit idle until interrupted spriteControl asl $d019 ; Acknowledge (clear) raster interrupt inc bordercolor ; Start a raster time status bar lda sprite0ybuffer ;copy buffers to actual locations sta sprite0ypos dec bordercolor ; stop raster time status bar jmp $ea81 ; Kernal routine to return to main program conv2dec LDY #$00 LDX sprite0yPrecision STX div_lo STY div_hi LDY #$04 next JSR div10 ORA #$30 STA $0400,Y DEY BPL next RTS div10 LDX #$11 LDA #$00 CLC loop ROL CMP #$0A BCC skip SBC #$0A CLV skip ROL div_lo ROL div_hi DEX BNE loop RTS *= $2000 !BIN "greenman.spr"