tschak909 Posted May 27, 2016 Share Posted May 27, 2016 Hello everybody, thought i'd paste this, a simple kernel for outputting playfield. The playfield data is vertically reflected, as well as horizontally reflected (like the combat playfield), and is nominally 8 scanlines deep. (yeah, I know it's not optimal, at all. I'm learning...) PROCESSOR 6502 include vcs.h include macro.h SEG.U VARS ORG $80 ScanLine: ds 1 ; scanline counter. SEG CODE ORG $F800 ColdStart: CLEAN_START MainLoop: jsr VerticalSync jsr VerticalBlank jsr Kernel jsr OverScan jmp MainLoop VerticalSync: lda #$02 ; Get ready to start VSYNC ldx #49 sta WSYNC ; Next line sta VSYNC ; Start VSYNC stx TIM64T sta CTRLPF sta WSYNC sta WSYNC lda #$00 sta PF0 sta PF1 sta PF2 sta WSYNC sta VSYNC Sleep12: rts VerticalBlank: ldx #3 ldy #3 lda SWCHB and #$08 bne SOCloop ldy #7 SOCloop: lda Colors,Y sta COLUP0,x dey dex bpl SOCloop rts Kernel: LDA #$01 STA CTRLPF sta WSYNC lda INTIM bne Kernel sta VBLANK sta WSYNC ldx #$00 kl0: ldy #$08 kl1: lda PF0_0,x sta PF0 lda PF1_0,x sta PF1 lda PF2_0,x sta PF2 sta WSYNC dey bne kl1 inx cpx #$0B bne kl0 kl2: ldy #$08 kl3: lda PF0_0,X sta PF0 lda PF1_0,x sta PF1 lda PF2_0,x sta PF2 sta WSYNC dey bne kl3 dex bpl kl2 sta PF0 sta PF1 sta PF2 rts OverScan: sta WSYNC lda #2 sta VBLANK lda #32 sta TIM64T OSWait: sta WSYNC lda INTIM bne OSWait rts Colors: .byte $86 .byte $C6 .byte $46 .byte $00 .byte $0E .byte $06 .byte $0A .byte $00 align 256 PF0_0 .byte $F0 ; |XXXX | .byte $10 ; | X | .byte $10 ; | X | .byte $10 ; | X | .byte $10 ; | X | .byte $10 ; | X | .byte $10 ; | X | .byte $10 ; | X | .byte $10 ; | X | .byte $10 ; | X | .byte $10 ; | X | .byte $10 ; | X | PF1_0 .byte $FF ; |XXXXXXXX| .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $38 ; | XXX | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $60 ; | XX | .byte $20 ; | X | .byte $20 ; | X | .byte $23 ; | X XX| PF2_0 .byte $FF ; |XXXXXXXX| .byte $80 ; |X | .byte $80 ; |X | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $1C ; | XXX | .byte $04 ; | X | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | .byte $00 ; | | ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;; Function to check for free space at end of cart. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; if (* & $FF) echo "!!!!! ", [$FFFA - *]d, "Bytes free before end of cartridge." align 256 endif ORG $FFFA .WORD ColdStart .WORD ColdStart .WORD ColdStart Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted May 27, 2016 Share Posted May 27, 2016 Note: for a non-asymmetrical playfield, you don't need to rewrite PF registers scanline-to-scanline unless the data is changing. This would draw the same thing and save 21 cycles on each successive scanline as Y counts down... Kernel: LDA #$01 STA CTRLPF sta WSYNC lda INTIM bne Kernel sta VBLANK sta WSYNC ldx #$00 kl0: ldy #$08 lda PF0_0,x sta PF0 lda PF1_0,x sta PF1 lda PF2_0,x sta PF2 k11: sta WSYNC dey bne kl1 inx cpx #$0B bne kl0 kl2: ldy #$08 lda PF0_0,X sta PF0 lda PF1_0,x sta PF1 lda PF2_0,x sta PF2 K13: sta WSYNC dey bne kl3 dex bpl kl2 sta PF0 sta PF1 sta PF2 rts Are the last 3 PF writes intended to clear the registers with zero? If so, you might want to store Y instead of A to each. Y is zero at the end of the subroutine, A is $FF. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted May 27, 2016 Share Posted May 27, 2016 Minor mistake with your free space check - you've merged the free space before page-aligned table if (* & $FF) echo "------", [(>.+1)*256 - .]d, "bytes free before DigitGfx" align 256 endif with free space at end of cartridge ;=============================================================================== ; free space check before End of Cartridge ;=============================================================================== echo "------", [$FFFA - *]d, "bytes free before End of Cartridge" Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 27, 2016 Author Share Posted May 27, 2016 Thanks, I was looking for replies, like this. I haven't gotten down to the bare metal in my day job in over two decades, so it's nice to be able to do this. I'm looking at the Combat source code, and I see tricks that were definitely done by people who had spent a LOT of time with the 6502...the stack trick is very clever... -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 29, 2016 Author Share Posted May 29, 2016 I tried another approach, inspired by the Combat kernel, and with the following code: ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;; Scratchpad to test ideas. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PROCESSOR 6502 include vcs.h include macro.h SEG.U VARS ORG $80 ScanLine: ds 1 ; scanline counter BallY0: ds 1 ; ball y0 SEG CODE ORG $F800 ColdStart: CLEAN_START MainLoop: jsr VerticalSync jsr VerticalBlank jsr Kernel jsr OverScan jmp MainLoop VerticalSync: lda #$02 ; Get ready to start VSYNC ldx #49 sta WSYNC ; Next line sta VSYNC ; Start VSYNC stx TIM64T sta CTRLPF sta WSYNC sta WSYNC lda #$00 sta PF0 sta PF1 sta PF2 sta WSYNC sta VSYNC Sleep12: rts VerticalBlank: ldx #3 ldy #3 lda SWCHB and #$08 bne SOCloop ldy #7 SOCloop: lda Colors,Y sta COLUP0,x dey dex bpl SOCloop lda SWCHB ; read switches lsr ; shift bit 0 into carry bcs norst ; and ignore if not pressed. sta RESP0 SLEEP 6 sta RESBL SLEEP 18 sta RESP1 lda #$20 sta BallY0 norst: rts Kernel: LDA #$01 STA CTRLPF sta WSYNC lda INTIM bne Kernel sta VBLANK lda #38 sta ScanLine sta WSYNC vmain: lda ScanLine bpl refl eor #$F8 refl: cmp #$20 bcc kend lsr lsr lsr tax kl0: lda PF0_0,x sta PF0 lda PF1_0,x sta PF1 lda PF2_0,x sta PF2 sta WSYNC inc ScanLine cmp #$EC bne vmain kend: rts OverScan: sta WSYNC lda #2 sta VBLANK lda #32 sta TIM64T OSWait: sta WSYNC lda INTIM bne OSWait rts Colors: .byte $86 .byte $C6 .byte $46 .byte $00 .byte $0E .byte $06 .byte $0A .byte $00 align 256 PF0_0 .byte $00 .byte $00 .byte $00 .byte $00 .byte $00 .byte $F0 ; |XXXX | $F779 .byte $10 ; | X | $F77A .byte $10 ; | X | $F77B .byte $10 ; | X | $F77C .byte $10 ; | X | $F77D .byte $10 ; | X | $F77E .byte $10 ; | X | $F77F .byte $10 ; | X | $F780 .byte $10 ; | X | $F781 .byte $10 ; | X | $F782 .byte $10 ; | X | $F783 .byte $10 ; | X | $F784 PF1_0 .byte $00 .byte $00 .byte $00 .byte $00 .byte $00 .byte $FF ; |XXXXXXXX| $F785 .byte $00 ; | | $F786 .byte $00 ; | | $F787 .byte $00 ; | | $F788 .byte $38 ; | XXX | $F789 .byte $00 ; | | $F78A .byte $00 ; | | $F78B .byte $00 ; | | $F78C .byte $60 ; | XX | $F78D .byte $20 ; | X | $F78E .byte $20 ; | X | $F78F .byte $23 ; | X XX| $F790 PF2_0 .byte $00 .byte $00 .byte $00 .byte $00 .byte $00 .byte $FF ; |XXXXXXXX| $F791 .byte $80 ; |X | $F792 .byte $80 ; |X | $F793 .byte $00 ; | | $F794 .byte $00 ; | | $F795 .byte $00 ; | | $F796 .byte $1C ; | XXX | $F797 .byte $04 ; | X | $F798 .byte $00 ; | | $F799 .byte $00 ; | | $F79A .byte $00 ; | | $F79B .byte $00 ; | | $F79C ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;; Function to check for free space at end of cart. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; echo "------", [$FFFA - *]d, "bytes free before End of Cartridge" ORG $FFFA .WORD ColdStart .WORD ColdStart .WORD ColdStart I got the following output: slight tearing on the extremes, and, i noticed that in the original Combat kernel, the pointers to the playfield data are offset negatively by 4, I had to do something similar here, is that to correct the offset bias so that the divide by 8 would work correctly? -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 29, 2016 Author Share Posted May 29, 2016 A bit more fenagling, and I can get a display, although i'm spilling over, need to see why... Why am I getting ripples? ... investigating... ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;; Scratchpad to test ideas. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PROCESSOR 6502 include vcs.h include macro.h SEG.U VARS ORG $80 ScanLine: ds 1 ; scanline counter BallY0: ds 1 ; ball y0 Score: ds 1 ; Score Timer: ds 1 ; Timer DigitOnes: ds 2 ; Player 0 and 1 digit graphics DigitTens: ds 2 ; Player 0 and 1 digit graphics ScoreGfx: ds 1 ; pointers TimerGfx: ds 1 ; pointers Temp: ds 1 ; Temp SEG CODE ORG $F800 ColdStart: CLEAN_START MainLoop: jsr VerticalSync jsr VerticalBlank jsr Kernel jsr OverScan jmp MainLoop VerticalSync: lda #$02 ; Get ready to start VSYNC ldx #45 sta WSYNC ; Next line sta VSYNC ; Start VSYNC stx TIM64T sta CTRLPF sta WSYNC sta WSYNC lda #$00 sta PF0 sta PF1 sta PF2 sta WSYNC sta VSYNC Sleep12: rts VerticalBlank: jsr SetColors jsr PrepScoreForDisplay rts Kernel: lda INTIM bne Kernel sta VBLANK lda #$20 sta ScanLine LDA #$02 STA CTRLPF sta WSYNC ldx #5 ScoreLoop: ldy DigitTens lda DigitGfx,y and #$f0 sta ScoreGfx ldy DigitOnes lda DigitGfx,y and #$0F ora ScoreGfx sta ScoreGfx sta WSYNC ;; sta PF1 ldy DigitTens+1 lda DigitGfx,y and #$F0 sta TimerGfx ldy DigitOnes+1 lda DigitGfx,y and #$0F ora TimerGfx sta TimerGfx jsr Sleep12 sta PF1 ldy ScoreGfx sta WSYNC sty PF1 inc DigitTens inc DigitTens+1 inc DigitOnes inc DigitOnes+1 jsr Sleep12 dex sta PF1 bne ScoreLoop sta WSYNC ;; stx PF1 sta WSYNC sta WSYNC lda #$01 sta CTRLPF vmain: sta WSYNC lda ScanLine bpl refl eor #$F8 refl: cmp #$20 bcc kend lsr lsr lsr tax kl0: lda PF0_0,x sta PF0 lda PF1_0,x sta PF1 lda PF2_0,x sta PF2 inc ScanLine lda ScanLine cmp #$EC bne vmain kend: rts OverScan: sta WSYNC lda #2 sta VBLANK lda #22 sta TIM64T OSWait: sta WSYNC lda INTIM bne OSWait rts SetColors: ldx #3 ldy #3 lda SWCHB and #$08 bne SOCloop ldy #7 SOCloop: lda Colors,Y sta COLUP0,x dey dex bpl SOCloop rts PrepScoreForDisplay: inc Timer bne PSFDskip inc Score PSFDskip: ldx #1 PSFDloop: lda Score,X and #$0F sta Temp asl asl adc Temp sta DigitOnes,x lda Score,x and #$F0 lsr lsr sta Temp lsr lsr adc Temp sta DigitTens,x dex bpl PSFDloop rts Colors: .byte $86 .byte $C6 .byte $46 .byte $00 .byte $0E .byte $06 .byte $0A .byte $00 align 256 PF0_0 .byte $00 .byte $00 .byte $00 .byte $00 .byte $F0 ; |XXXX | $F779 .byte $10 ; | X | $F77A .byte $10 ; | X | $F77B .byte $10 ; | X | $F77C .byte $10 ; | X | $F77D .byte $10 ; | X | $F77E .byte $10 ; | X | $F77F .byte $10 ; | X | $F780 .byte $10 ; | X | $F781 .byte $10 ; | X | $F782 .byte $10 ; | X | $F783 .byte $10 ; | X | $F784 PF1_0 .byte $00 .byte $00 .byte $00 .byte $00 .byte $FF ; |XXXXXXXX| $F785 .byte $00 ; | | $F786 .byte $00 ; | | $F787 .byte $00 ; | | $F788 .byte $38 ; | XXX | $F789 .byte $00 ; | | $F78A .byte $00 ; | | $F78B .byte $00 ; | | $F78C .byte $60 ; | XX | $F78D .byte $20 ; | X | $F78E .byte $20 ; | X | $F78F .byte $23 ; | X XX| $F790 PF2_0 .byte $00 .byte $00 .byte $00 .byte $00 .byte $FF ; |XXXXXXXX| $F791 .byte $80 ; |X | $F792 .byte $80 ; |X | $F793 .byte $00 ; | | $F794 .byte $00 ; | | $F795 .byte $00 ; | | $F796 .byte $1C ; | XXX | $F797 .byte $04 ; | X | $F798 .byte $00 ; | | $F799 .byte $00 ; | | $F79A .byte $00 ; | | $F79B .byte $00 ; | | $F79C DigitGfx: .byte %01110111 .byte %01010101 .byte %01010101 .byte %01010101 .byte %01110111 .byte %00010001 .byte %00010001 .byte %00010001 .byte %00010001 .byte %00010001 .byte %01110111 .byte %00010001 .byte %01110111 .byte %01000100 .byte %01110111 .byte %01110111 .byte %00010001 .byte %00110011 .byte %00010001 .byte %01110111 .byte %01010101 .byte %01010101 .byte %01110111 .byte %00010001 .byte %00010001 .byte %01110111 .byte %01000100 .byte %01110111 .byte %00010001 .byte %01110111 .byte %01110111 .byte %01000100 .byte %01110111 .byte %01010101 .byte %01110111 .byte %01110111 .byte %00010001 .byte %00010001 .byte %00010001 .byte %00010001 .byte %01110111 .byte %01010101 .byte %01110111 .byte %01010101 .byte %01110111 .byte %01110111 .byte %01010101 .byte %01110111 .byte %00010001 .byte %01110111 .byte %00100010 .byte %01010101 .byte %01110111 .byte %01010101 .byte %01010101 .byte %01100110 .byte %01010101 .byte %01100110 .byte %01010101 .byte %01100110 .byte %00110011 .byte %01000100 .byte %01000100 .byte %01000100 .byte %00110011 .byte %01100110 .byte %01010101 .byte %01010101 .byte %01010101 .byte %01100110 .byte %01110111 .byte %01000100 .byte %01100110 .byte %01000100 .byte %01110111 .byte %01110111 .byte %01000100 .byte %01100110 .byte %01000100 .byte %01000100 ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;; Function to check for free space at end of cart. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; echo "------", [$FFFA - *]d, "bytes free before End of Cartridge" ORG $FFFA .WORD ColdStart .WORD ColdStart .WORD ColdStart Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 29, 2016 Author Share Posted May 29, 2016 scooting the STA WSYNC from the beginning of Vmain to the lda/sta of pf0, fixed the ripple... stella debugger proving insanely useful here. -Thom Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted May 29, 2016 Share Posted May 29, 2016 When you update the various TIA registers can be time critical, so you should get in the habit of adding cycle counts to your kernel. An example from Collect: ScoreLoop: ; 43 - cycle after bpl ScoreLoop ldy DigitTens ; 3 46 - get the tens digit offset for the Score lda DigitGfx,y ; 5 51 - use it to load the digit graphics and #$F0 ; 2 53 - remove the graphics for the ones digit sta ScoreGfx ; 3 56 - and save it ldy DigitOnes ; 3 59 - get the ones digit offset for the Score lda DigitGfx,y ; 5 64 - use it to load the digit graphics and #$0F ; 2 66 - remove the graphics for the tens digit ora ScoreGfx ; 3 69 - merge with the tens digit graphics sta ScoreGfx ; 3 72 - and save it sta WSYNC ; 3 75 - wait for end of scanline ;--------------------------------------- sta PF1 ; 3 3 - @66-28, update playfield for Score dislay ldy DigitTens+1 ; 3 6 - get the left digit offset for the Score+1 lda DigitGfx,y ; 5 11 - use it to load the digit graphics and #$F0 ; 2 13 - remove the graphics for the ones digit sta ScoreGfx+1 ; 3 16 - and save it ldy DigitOnes+1 ; 3 19 - get the ones digit offset for the Score+1 lda DigitGfx,y ; 5 24 - use it to load the digit graphics and #$0F ; 2 26 - remove the graphics for the tens digit ora ScoreGfx+1 ; 3 29 - merge with the tens digit graphics sta ScoreGfx+1 ; 3 32 - and save it jsr Sleep12 ;12 44 - waste some cycles sta PF1 ; 3 47 - @39-54, update playfield for Score+1 display ldy ScoreGfx ; 3 50 - preload for next scanline sta WSYNC ; 3 53 - wait for end of scanline ;--------------------------------------- sty PF1 ; 3 3 - update playfield for the Score display inc DigitTens ; 5 8 - advance for the next line of graphic data inc DigitTens+1 ; 5 13 - advance for the next line of graphic data inc DigitOnes ; 5 18 - advance for the next line of graphic data inc DigitOnes+1 ; 5 23 - advance for the next line of graphic data jsr Sleep12 ;12 35 - waste some cycles dex ; 2 37 - decrease the loop counter sta PF1 ; 3 40 - @39-54, update playfield for the Score+1 display bne ScoreLoop ; 2 42 - (3 43) if dex != 0 then branch to ScoreLoop sta WSYNC ; 3 45 - wait for end of scanline The first number after each ; is the number of cycles that instruction will take. The second number is cumulative cycles for that line AFTER the instruction finishes. Some lines have an @xx-yy to denote the acceptable cycles for updating a time-critical TIA register. Additionally, branches show the timing for when the branch is not taken, followed by parentheses containing the timing if the branch is taken.Collect Step 3 covers the time critical updates for the PFx registers, and includes a handy diagram that Andrew Davie posted. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted May 29, 2016 Author Share Posted May 29, 2016 Yup, I know, I need to get into the habit. I'm thinking through an extension to the emacs assembler mode, that would take a selection and add cycle counts... hmm.... on another note, am working on some ball code. Trying to replicate the billiard mode combat physics... -Thom Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.