1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-11-24 12:31:25 +00:00
8bitworkshop/presets/vcs/examples/complexscene2.a
2018-09-30 21:07:45 -04:00

298 lines
6.2 KiB
Plaintext

processor 6502
include "vcs.h"
include "macro.h"
include "xmacro.h"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; This example demonstrates a scene with a full-screen
; playfield, and two sprites overlapping it. This takes more
; CPU time, so our kernel operates in 4-line chunks.
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
seg.u Variables
org $80
PFPtr word ; pointer to playfield data
PFIndex byte ; offset into playfield array
PFCount byte ; lines left in this playfield segment
YPos0 byte ; Y position of player 0 sprite
XPos0 byte ; X position of player 0 sprite
YPos1 byte ; Y position of player 1 sprite
XPos1 byte ; X position of player 1 sprite
; pointers to bitmap and color tables
SpritePtr0 word
ColorPtr0 word
SpritePtr1 word
ColorPtr1 word
; temporary values for kernel
YP0 byte ; Y counter for player 0
YP1 byte ; Y counter for player 1
Temp byte
Bitp0 byte
Bitp1 byte
Colp0 byte
Colp1 byte
tmpPF0 byte
tmpPF1 byte
tmpPF2 byte
SpriteHeight equ 16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
seg Code
org $f000
Start
CLEAN_START
Data0
; set up pointers to playfield and sprites
lda #<Data0
sta PFPtr
lda #>Data0
sta PFPtr+1
lda #<Frame0
sta SpritePtr0
lda #>Frame0
sta SpritePtr0+1
lda #<ColorFrame0
sta ColorPtr0
lda #>ColorFrame0
sta ColorPtr0+1
lda #<Frame0
sta SpritePtr1
lda #>Frame0
sta SpritePtr1+1
lda #<ColorFrame0
sta ColorPtr1
lda #>ColorFrame0
sta ColorPtr1+1
; set up initial positions
lda #242
sta YPos0
lda #200
sta YPos1
lda #38
sta XPos0
sta XPos1
lda #1
sta VDELP0 ; updates to GRP0 will be delayed
NextFrame
VERTICAL_SYNC
; Set up VBLANK timer
TIMER_SETUP 37
lda #$88
sta COLUBK ; bg color
lda #$5b
sta COLUPF ; fg color
lda #$68
sta COLUP0 ; player color
lda #1
sta CTRLPF ; symmetry
lda #72
sta PFIndex ; reset playfield offset
; Set temporary Y counter and set horizontal position
lda YPos0
sta YP0 ; yp0 = temporary counter
lda YPos1
sta YP1 ; yp0 = temporary counter
lda XPos0
ldx #0
jsr SetHorizPos
lda XPos1
ldx #1
jsr SetHorizPos
sta WSYNC
sta HMOVE ; gotta apply HMOVE
; Wait for end of VBLANK
TIMER_WAIT
lda #0
sta VBLANK
SLEEP 31 ; so timing analysis works out
KernelLoop
; Phase 0: Fetch PF0 byte
jsr DrawSprites
ldy PFIndex ; no more playfield?
beq NoMoreLines ; exit loop
dey
lda (PFPtr),y ; load PF0
sty PFIndex
sta tmpPF0
; Phase 1: Fetch PF1 byte
jsr DrawSprites
ldy PFIndex
dey
lda (PFPtr),y ; load PF1
sty PFIndex
sta tmpPF1
; Phase 2: Fetch PF2 byte
jsr DrawSprites
ldy PFIndex
dey
lda (PFPtr),y ; load PF2
sty PFIndex
sta tmpPF2
; Phase 3: Write PF0/PF1/PF2 registers
jsr DrawSprites
lda tmpPF0
sta PF0
lda tmpPF1
sta PF1
lda tmpPF2
sta PF2
; Go to next scanline
jmp KernelLoop
NoMoreLines
; Set up overscan timer
TIMER_SETUP 27
lda #2
sta VBLANK
jsr MoveJoystick
TIMER_WAIT
jmp NextFrame
; DrawSprite subroutine called by kernel
DrawSprites
; Fetch sprite 0 values
lda #SpriteHeight ; height in 2xlines
sec
isb YP0 ; INC yp0, then SBC yp0
bcs DoDraw0 ; inside bounds?
lda #0 ; no, load the padding offset (0)
DoDraw0
tay ; -> Y
lda (ColorPtr0),y ; color for both lines
sta Colp0 ; -> colp0
lda (SpritePtr0),y ; bitmap for first line
sta GRP0 ; -> [GRP0] (delayed due to VDEL)
; Fetch sprite 1 values
lda #SpriteHeight ; height in 2xlines
sec
isb YP1 ; INC yp0, then SBC yp0
bcs DoDraw1 ; inside bounds?
lda #0 ; no, load the padding offset (0)
DoDraw1
tay ; -> Y
lda (ColorPtr1),y ; color for both lines
tax
lda (SpritePtr1),y ; bitmap for first line
tay
; WSYNC and store sprite values
lda Colp0
sta WSYNC
sty GRP1 ; GRP0 is also updated due to VDELP0 flag
stx COLUP1
sta COLUP0
; Return to caller
rts
SetHorizPos
sta WSYNC ; start a new line
bit 0 ; waste 3 cycles
sec ; set carry flag
DivideLoop
sbc #15 ; subtract 15
bcs DivideLoop ; branch until negative
eor #7 ; calculate fine offset
asl
asl
asl
asl
sta RESP0,x ; fix coarse position
sta HMP0,x ; set fine offset
rts ; return to caller
; Read joystick movement and apply to object 0
MoveJoystick
; Move vertically
; (up and down are actually reversed since ypos starts at bottom)
ldx YPos0
lda #%00100000 ;Up?
bit SWCHA
bne SkipMoveUp
cpx #175
bcc SkipMoveUp
dex
SkipMoveUp
lda #%00010000 ;Down?
bit SWCHA
bne SkipMoveDown
cpx #254
bcs SkipMoveDown
inx
SkipMoveDown
stx YPos0
; Move horizontally
ldx XPos0
lda #%01000000 ;Left?
bit SWCHA
bne SkipMoveLeft
cpx #1
bcc SkipMoveLeft
dex
SkipMoveLeft
lda #%10000000 ;Right?
bit SWCHA
bne SkipMoveRight
cpx #153
bcs SkipMoveRight
inx
SkipMoveRight
stx XPos0
rts
; Bitmap data "standing" position
Frame0
.byte #0
.byte #%01101100;$F6
.byte #%00101000;$86
.byte #%00101000;$86
.byte #%00111000;$86
.byte #%10111010;$C2
.byte #%10111010;$C2
.byte #%01111100;$C2
.byte #%00111000;$C2
.byte #%00111000;$16
.byte #%01000100;$16
.byte #%01111100;$16
.byte #%01111100;$18
.byte #%01010100;$18
.byte #%01111100;$18
.byte #%11111110;$F2
.byte #%00111000;$F4
; Color data for each line of sprite
ColorFrame0
.byte #$FF;
.byte #$F6;
.byte #$86;
.byte #$86;
.byte #$86;
.byte #$C2;
.byte #$C2;
.byte #$C2;
.byte #$C2;
.byte #$16;
.byte #$16;
.byte #$16;
.byte #$18;
.byte #$18;
.byte #$18;
.byte #$F2;
.byte #$F4;
; Epilogue
org $fffc
.word Start
.word Start