mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-24 12:31:25 +00:00
253 lines
6.6 KiB
Plaintext
253 lines
6.6 KiB
Plaintext
|
|
processor 6502
|
|
include "vcs.h"
|
|
include "macro.h"
|
|
|
|
org $f000
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;
|
|
; Now, we'll finally put everything together and
|
|
; make a little person with a hat that can move
|
|
; back and forth and throw rocks. We'll use one player
|
|
; to generate a 8x16 sprite and one missile.
|
|
;
|
|
; We have two tables for the sprite, a bitmap table and
|
|
; a color table. We'll lookup from both of these tables on
|
|
; each scanline.
|
|
;
|
|
; Because VCS programming is all about thrift, we'll
|
|
; reuse the machine code for our program as the backdrop
|
|
; for the playfield, just to show we can fit it all on
|
|
; a scanline.
|
|
;
|
|
; Note: the Y coordinate goes bottom-top, not top-bottom
|
|
; as in the next section.
|
|
;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
counter equ $81 ; increments each frame
|
|
yplyr equ $82 ; player y pos
|
|
yrock equ $83 ; rock y pos
|
|
animofs equ $84 ; sprite data offset, used for animation
|
|
|
|
; Initialize and set initial offsets of objects.
|
|
start CLEAN_START
|
|
lda #5
|
|
sta yplyr
|
|
lda #70
|
|
ldx #0
|
|
jsr SetHorizPos ; set player 0 horiz. pos
|
|
sta WSYNC
|
|
sta HMOVE
|
|
|
|
; Next frame loop
|
|
nextframe
|
|
VERTICAL_SYNC
|
|
|
|
; in case the rock is on screen
|
|
lda ColorFrame0 ; load 1st entry of color data
|
|
sta COLUP0 ; set sprite 0 color
|
|
|
|
; 37 lines of VBLANK
|
|
ldx #37
|
|
lvblank sta WSYNC
|
|
dex
|
|
bne lvblank
|
|
|
|
; set some colors
|
|
lda #$80
|
|
sta COLUBK ; set the background color
|
|
lda #1
|
|
sta CTRLPF ; playfield reflection
|
|
|
|
; Draw 192 scanlines with our sprite/missile kernel
|
|
ldx #192
|
|
lvscan
|
|
; Draw sprite?
|
|
txa
|
|
sec ; make sure carry is set (meaning no borrow for subtraction)
|
|
sbc yplyr ; get offset into sprite for this line
|
|
cmp #SpriteHeight ; sprite is 16 pixels high + padding on either side
|
|
bcc insprite
|
|
lda #SpriteHeight-1 ; draw the padding
|
|
insprite
|
|
tay
|
|
lda ColorFrame0,y ; load color data
|
|
pha ; push color data onto stack
|
|
clc ; clear carry flag
|
|
adc animofs ; add animation offset (not for color though)
|
|
lda Frame0,y ; load bitmap data
|
|
sta WSYNC ; wait for next scanline (as late as possible!)
|
|
sta GRP0 ; set sprite 0 pixels
|
|
pla ; pull bitmap data from stack
|
|
sta COLUP0 ; set sprite 0 color
|
|
lda start,x ; store some random garbage into the playfield
|
|
sta PF0
|
|
sta PF1
|
|
sta PF2
|
|
; Draw rock? Player 0 and missile 0 share a color register,
|
|
; so they will have the same colors on the same scanline
|
|
lda #%00000000
|
|
cpx yrock
|
|
bne norock
|
|
lda #%00000010 ; for ENAM0 the 2nd bit is enable
|
|
norock
|
|
sta ENAM0 ; enable missile 0
|
|
dex
|
|
bne lvscan ; repeat next scanline until finished
|
|
; End of scanline loop
|
|
|
|
; Clear all colors to black before overscan
|
|
stx COLUBK
|
|
stx COLUP0
|
|
stx COLUP1
|
|
stx COLUPF
|
|
; 30 lines of overscan
|
|
ldx #29
|
|
lvover sta WSYNC
|
|
dex
|
|
bne lvover
|
|
|
|
; Joystick movement
|
|
; For up and down, we INC or DEC the Y Position
|
|
lda #%00010000 ;Up?
|
|
bit SWCHA
|
|
bne SkipMoveUp
|
|
inc yplyr
|
|
SkipMoveUp
|
|
lda #%00100000 ;Down?
|
|
bit SWCHA
|
|
bne SkipMoveDown
|
|
dec yplyr
|
|
SkipMoveDown
|
|
; Note that the horizontal position is not contained in RAM,
|
|
; but inaccessibly inside the TIA's registers! Some games can
|
|
; get away with this if they use the collision registers.
|
|
ldx #0 ; assume speed is 0 if no movement
|
|
lda #%01000000 ;Left?
|
|
bit SWCHA
|
|
bne SkipMoveLeft
|
|
ldx #$10 ;a 1 in the left nibble means go left
|
|
SkipMoveLeft
|
|
lda #%10000000 ;Right?
|
|
bit SWCHA
|
|
bne SkipMoveRight
|
|
ldx #$F0 ;a -1 in the left nibble means go right...
|
|
SkipMoveRight
|
|
stx HMP0 ;set the move for plyr 0
|
|
sta WSYNC
|
|
sta HMOVE
|
|
; Throw a rock when fire button pressed
|
|
lda #0
|
|
sta animofs
|
|
ldy #%00000000 ; use later to enable/disable missile lock on player
|
|
lda INPT4 ;read button input
|
|
bmi ButtonNotPressed ;skip if button not pressed
|
|
lda yplyr
|
|
sta yrock ; set rock vert pos to player's vert
|
|
lda #SpriteHeight
|
|
sta animofs ; while button pressed, use alternate player bitmap
|
|
ldy #%00000010 ; for RESMP0 the 2nd bit is the enable bit
|
|
ButtonNotPressed
|
|
sty RESMP0 ; reset missile 0 to player 0's horiz position
|
|
inc yrock ; rock moves no matter what (actually a boomerang)
|
|
|
|
; Goto next frame
|
|
jmp nextframe
|
|
|
|
; SetHorizPos - Sets the horizontal position of an object.
|
|
; The X register contains the index of the desired object:
|
|
; X=0: player 0
|
|
; X=1: player 1
|
|
; X=2: missile 0
|
|
; X=3: missile 1
|
|
; X=4: ball
|
|
; This routine does a WSYNC and HMOVE before executing,
|
|
; so whatever you do here will not take effect until you
|
|
; call the routine again or do your own WSYNC and HMOVE.
|
|
SetHorizPos
|
|
sta WSYNC ; start a new line
|
|
sta HMOVE ; apply the previous fine position(s)
|
|
sta HMCLR ; reset the old horizontal position(s)
|
|
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
|
|
|
|
; Height of our sprite in lines
|
|
SpriteHeight equ 18
|
|
|
|
; 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
|
|
|
|
; Bitmap data "throwing" position
|
|
Frame1
|
|
.byte #0
|
|
.byte #%01101100;$F6
|
|
.byte #%01000100;$86
|
|
.byte #%00101000;$86
|
|
.byte #%00111000;$86
|
|
.byte #%10111010;$C2
|
|
.byte #%10111101;$C2
|
|
.byte #%01111101;$C2
|
|
.byte #%00111001;$C2
|
|
.byte #%00111000;$16
|
|
.byte #%01101100;$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 ; rock color if not sharing line with player sprite
|
|
.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
|