mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-16 17:30:27 +00:00
vcs: added chap 8, 11, 12, 13 examples
This commit is contained in:
parent
d9b40a566d
commit
e852fd27a6
@ -130,6 +130,11 @@ TODO:
|
||||
- support NES_HEADER_16K?
|
||||
- PPU/TIA register write visualization
|
||||
- NES crt should mark raster pos when debugging
|
||||
- JSNES
|
||||
- doesn't support hiding >8 sprites
|
||||
- doesn't do sprite zero test right
|
||||
- doesn't do clip right
|
||||
- doesn't do b/w tint
|
||||
- vcs
|
||||
- need Chapter 8 example?
|
||||
- vcs sound continues when paused
|
||||
|
103
presets/vcs/examples/colorsprites.a
Normal file
103
presets/vcs/examples/colorsprites.a
Normal file
@ -0,0 +1,103 @@
|
||||
|
||||
processor 6502
|
||||
include "vcs.h"
|
||||
include "macro.h"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;
|
||||
; We can draw a color sprite by setting two registers
|
||||
; on every scanline:
|
||||
; GRP0 (the bitmap) and COLUP0 (the player color).
|
||||
; There's a separate lookup table for each.
|
||||
;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
SpriteHeight equ 8
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Variables segment
|
||||
|
||||
seg.u Variables
|
||||
org $80
|
||||
|
||||
YPos .byte
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Code segment
|
||||
|
||||
seg Code
|
||||
org $f000
|
||||
|
||||
Start
|
||||
CLEAN_START
|
||||
|
||||
lda #5
|
||||
sta YPos
|
||||
|
||||
NextFrame
|
||||
lsr SWCHB ; test Game Reset switch
|
||||
bcc Start ; reset?
|
||||
; 1 + 3 lines of VSYNC
|
||||
VERTICAL_SYNC
|
||||
; 37 lines of underscan
|
||||
ldx #37
|
||||
LVBlank sta WSYNC
|
||||
dex
|
||||
bne LVBlank
|
||||
; 192 lines of frame
|
||||
ldx #192 ; X = 192 scanlines
|
||||
LVScan
|
||||
txa ; X -> A
|
||||
sec ; set carry for subtract
|
||||
sbc YPos ; local coordinate
|
||||
cmp #SpriteHeight ; in sprite?
|
||||
bcc InSprite ; yes, skip over next
|
||||
lda #0 ; not in sprite, load 0
|
||||
InSprite
|
||||
tay ; local coord -> Y
|
||||
lda Frame0,y ; lookup color
|
||||
sta WSYNC ; sync w/ scanline
|
||||
sta GRP0 ; store bitmap
|
||||
lda ColorFrame0,y ; lookup color
|
||||
sta COLUP0 ; store color
|
||||
dex ; decrement X
|
||||
bne LVScan ; repeat until 192 lines
|
||||
|
||||
; 29 lines of overscan
|
||||
ldx #29
|
||||
LVOver sta WSYNC
|
||||
dex
|
||||
bne LVOver
|
||||
; total = 262 lines, go to next frame
|
||||
jmp NextFrame
|
||||
|
||||
; Cat-head graphics data
|
||||
Frame0
|
||||
.byte #0 ; zero padding, also clears register
|
||||
.byte #%00111100
|
||||
.byte #%01000010
|
||||
.byte #%11100111
|
||||
.byte #%11111111
|
||||
.byte #%10011001
|
||||
.byte #%01111110
|
||||
.byte #%11000011
|
||||
.byte #%10000001
|
||||
|
||||
; Cat-head color data
|
||||
ColorFrame0
|
||||
.byte #0 ; unused (for now)
|
||||
.byte #$AE
|
||||
.byte #$AC
|
||||
.byte #$A8
|
||||
.byte #$AC
|
||||
.byte #$8E
|
||||
.byte #$8E
|
||||
.byte #$98
|
||||
.byte #$94
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Epilogue
|
||||
|
||||
org $fffc
|
||||
.word Start ; reset vector
|
||||
.word Start ; BRK vector
|
176
presets/vcs/examples/controls.a
Normal file
176
presets/vcs/examples/controls.a
Normal file
@ -0,0 +1,176 @@
|
||||
|
||||
processor 6502
|
||||
include "vcs.h"
|
||||
include "macro.h"
|
||||
include "xmacro.h"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;
|
||||
; We're going to set the player's coarse and fine position
|
||||
; at the same time using a clever method.
|
||||
; We divide the X coordinate by 15, in a loop that itself
|
||||
; is 15 cycles long. When the loop exits, we are at
|
||||
; the correct coarse position, and we set RESP0.
|
||||
; The accumulator holds the remainder, which we convert
|
||||
; into the fine position for the HMP0 register.
|
||||
; This logic is in a subroutine called SetHorizPos.
|
||||
;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
SpriteHeight equ 8
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Variables segment
|
||||
|
||||
seg.u Variables
|
||||
org $80
|
||||
|
||||
XPos .byte
|
||||
YPos .byte
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Code segment
|
||||
|
||||
seg Code
|
||||
org $f000
|
||||
|
||||
Start
|
||||
CLEAN_START
|
||||
|
||||
lda #80
|
||||
sta YPos
|
||||
sta XPos
|
||||
|
||||
NextFrame
|
||||
lsr SWCHB ; test Game Reset switch
|
||||
bcc Start ; reset?
|
||||
; 1 + 3 lines of VSYNC
|
||||
VERTICAL_SYNC
|
||||
; 37 lines of underscan
|
||||
TIMER_SETUP 37
|
||||
; move X and Y coordinates w/ joystick
|
||||
jsr MoveJoystick
|
||||
; the next two scanlines
|
||||
; position the player horizontally
|
||||
lda XPos ; get X coordinate
|
||||
ldx #0 ; player 0
|
||||
jsr SetHorizPos ; set coarse offset
|
||||
sta WSYNC ; sync w/ scanline
|
||||
sta HMOVE ; apply fine offsets
|
||||
; it's ok if we took an extra scanline because
|
||||
; the PIA timer will always count 37 lines
|
||||
; wait for end of underscan
|
||||
TIMER_WAIT
|
||||
; 192 lines of frame
|
||||
ldx #192 ; X = 192 scanlines
|
||||
LVScan
|
||||
txa ; X -> A
|
||||
sec ; set carry for subtract
|
||||
sbc YPos ; local coordinate
|
||||
cmp #SpriteHeight ; in sprite?
|
||||
bcc InSprite ; yes, skip over next
|
||||
lda #0 ; not in sprite, load 0
|
||||
InSprite
|
||||
tay ; local coord -> Y
|
||||
lda Frame0,y ; lookup color
|
||||
sta WSYNC ; sync w/ scanline
|
||||
sta GRP0 ; store bitmap
|
||||
lda ColorFrame0,y ; lookup color
|
||||
sta COLUP0 ; store color
|
||||
dex ; decrement X
|
||||
bne LVScan ; repeat until 192 lines
|
||||
|
||||
; 29 lines of overscan
|
||||
TIMER_SETUP 29
|
||||
TIMER_WAIT
|
||||
; total = 262 lines, go to next frame
|
||||
jmp NextFrame
|
||||
|
||||
; SetHorizPos routine
|
||||
; A = X coordinate
|
||||
; X = player number (0 or 1)
|
||||
SetHorizPos
|
||||
sta WSYNC ; start a new line
|
||||
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 YPos
|
||||
lda #%00100000 ;Up?
|
||||
bit SWCHA
|
||||
bne SkipMoveUp
|
||||
cpx #2
|
||||
bcc SkipMoveUp
|
||||
dex
|
||||
SkipMoveUp
|
||||
lda #%00010000 ;Down?
|
||||
bit SWCHA
|
||||
bne SkipMoveDown
|
||||
cpx #183
|
||||
bcs SkipMoveDown
|
||||
inx
|
||||
SkipMoveDown
|
||||
stx YPos
|
||||
; Move horizontally
|
||||
ldx XPos
|
||||
lda #%01000000 ;Left?
|
||||
bit SWCHA
|
||||
bne SkipMoveLeft
|
||||
cpx #16
|
||||
bcc SkipMoveLeft
|
||||
dex
|
||||
SkipMoveLeft
|
||||
lda #%10000000 ;Right?
|
||||
bit SWCHA
|
||||
bne SkipMoveRight
|
||||
cpx #153
|
||||
bcs SkipMoveRight
|
||||
inx
|
||||
SkipMoveRight
|
||||
stx XPos
|
||||
rts
|
||||
|
||||
|
||||
; Cat-head graphics data
|
||||
Frame0
|
||||
.byte #0 ; zero padding, also clears register
|
||||
.byte #%00111100
|
||||
.byte #%01000010
|
||||
.byte #%11100111
|
||||
.byte #%11111111
|
||||
.byte #%10011001
|
||||
.byte #%01111110
|
||||
.byte #%11000011
|
||||
.byte #%10000001
|
||||
|
||||
; Cat-head color data
|
||||
ColorFrame0
|
||||
.byte #0 ; unused (for now)
|
||||
.byte #$AE
|
||||
.byte #$AC
|
||||
.byte #$A8
|
||||
.byte #$AC
|
||||
.byte #$8E
|
||||
.byte #$8E
|
||||
.byte #$98
|
||||
.byte #$94
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Epilogue
|
||||
|
||||
org $fffc
|
||||
.word Start ; reset vector
|
||||
.word Start ; BRK vector
|
51
presets/vcs/examples/piatimer.a
Normal file
51
presets/vcs/examples/piatimer.a
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
processor 6502
|
||||
include "vcs.h"
|
||||
include "macro.h"
|
||||
include "xmacro.h"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Variables segment
|
||||
|
||||
seg.u Variables
|
||||
org $80
|
||||
|
||||
Temp .byte
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Code segment
|
||||
|
||||
seg Code
|
||||
org $f000
|
||||
|
||||
Start
|
||||
CLEAN_START
|
||||
|
||||
NextFrame
|
||||
lsr SWCHB ; test Game Reset switch
|
||||
bcc Start ; reset?
|
||||
; 1 + 3 lines of VSYNC
|
||||
VERTICAL_SYNC
|
||||
; 37 lines of underscan
|
||||
TIMER_SETUP 37
|
||||
TIMER_WAIT
|
||||
; 192 lines of frame
|
||||
TIMER_SETUP 192
|
||||
; draw colors based on timer value
|
||||
LRainbow
|
||||
lda INTIM ; load timer
|
||||
sta COLUBK ; store background
|
||||
bne LRainbow ; loop until timer == 0
|
||||
TIMER_WAIT ; timer is already 0, no-op
|
||||
; 29 lines of overscan
|
||||
TIMER_SETUP 29
|
||||
TIMER_WAIT
|
||||
; total = 262 lines, go to next frame
|
||||
jmp NextFrame
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Epilogue
|
||||
|
||||
org $fffc
|
||||
.word Start ; reset vector
|
||||
.word Start ; BRK vector
|
140
presets/vcs/examples/sethorizpos.a
Normal file
140
presets/vcs/examples/sethorizpos.a
Normal file
@ -0,0 +1,140 @@
|
||||
|
||||
processor 6502
|
||||
include "vcs.h"
|
||||
include "macro.h"
|
||||
include "xmacro.h"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;
|
||||
; We're going to set the player's coarse and fine position
|
||||
; at the same time using a clever method.
|
||||
; We divide the X coordinate by 15, in a loop that itself
|
||||
; is 15 cycles long. When the loop exits, we are at
|
||||
; the correct coarse position, and we set RESP0.
|
||||
; The accumulator holds the remainder, which we convert
|
||||
; into the fine position for the HMP0 register.
|
||||
; This logic is in a subroutine called SetHorizPos.
|
||||
;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
SpriteHeight equ 8
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Variables segment
|
||||
|
||||
seg.u Variables
|
||||
org $80
|
||||
|
||||
XPos .byte
|
||||
YPos .byte
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Code segment
|
||||
|
||||
seg Code
|
||||
org $f000
|
||||
|
||||
Start
|
||||
CLEAN_START
|
||||
|
||||
lda #5
|
||||
sta YPos
|
||||
sta XPos
|
||||
|
||||
NextFrame
|
||||
lsr SWCHB ; test Game Reset switch
|
||||
bcc Start ; reset?
|
||||
; 1 + 3 lines of VSYNC
|
||||
VERTICAL_SYNC
|
||||
; 35 lines of underscan
|
||||
ldx #35
|
||||
LVBlank sta WSYNC
|
||||
dex
|
||||
bne LVBlank
|
||||
; animate X and Y coordinates
|
||||
; NOTE: when X is too close to the right side,
|
||||
; we risk using an extra scanline
|
||||
inc XPos
|
||||
inc YPos
|
||||
; the next two scanlines
|
||||
; position the player horizontally
|
||||
lda XPos ; get X coordinate
|
||||
ldx #0 ; player 0
|
||||
jsr SetHorizPos ; set coarse offset
|
||||
sta WSYNC ; sync w/ scanline
|
||||
sta HMOVE ; apply fine offsets
|
||||
; 192 lines of frame
|
||||
ldx #192 ; X = 192 scanlines
|
||||
LVScan
|
||||
txa ; X -> A
|
||||
sec ; set carry for subtract
|
||||
sbc YPos ; local coordinate
|
||||
cmp #SpriteHeight ; in sprite?
|
||||
bcc InSprite ; yes, skip over next
|
||||
lda #0 ; not in sprite, load 0
|
||||
InSprite
|
||||
tay ; local coord -> Y
|
||||
lda Frame0,y ; lookup color
|
||||
sta WSYNC ; sync w/ scanline
|
||||
sta GRP0 ; store bitmap
|
||||
lda ColorFrame0,y ; lookup color
|
||||
sta COLUP0 ; store color
|
||||
dex ; decrement X
|
||||
bne LVScan ; repeat until 192 lines
|
||||
|
||||
; 29 lines of overscan
|
||||
ldx #29
|
||||
LVOver sta WSYNC
|
||||
dex
|
||||
bne LVOver
|
||||
; total = 262 lines, go to next frame
|
||||
jmp NextFrame
|
||||
|
||||
; SetHorizPos routine
|
||||
; A = X coordinate
|
||||
; X = player number (0 or 1)
|
||||
SetHorizPos
|
||||
sta WSYNC ; start a new line
|
||||
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
|
||||
|
||||
; Cat-head graphics data
|
||||
Frame0
|
||||
.byte #0 ; zero padding, also clears register
|
||||
.byte #%00111100
|
||||
.byte #%01000010
|
||||
.byte #%11100111
|
||||
.byte #%11111111
|
||||
.byte #%10011001
|
||||
.byte #%01111110
|
||||
.byte #%11000011
|
||||
.byte #%10000001
|
||||
|
||||
; Cat-head color data
|
||||
ColorFrame0
|
||||
.byte #0 ; unused (for now)
|
||||
.byte #$AE
|
||||
.byte #$AC
|
||||
.byte #$A8
|
||||
.byte #$AC
|
||||
.byte #$8E
|
||||
.byte #$8E
|
||||
.byte #$98
|
||||
.byte #$94
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Epilogue
|
||||
|
||||
org $fffc
|
||||
.word Start ; reset vector
|
||||
.word Start ; BRK vector
|
@ -14,8 +14,12 @@ const VCS_PRESETS = [
|
||||
{id:'examples/vsync.a', chapter:5, name:'Painting on the CRT', title:'Color Bars'},
|
||||
{id:'examples/playfield.a', chapter:6, name:'Playfield Graphics'},
|
||||
{id:'examples/sprite.a', chapter:7, name:'Players and Sprites'},
|
||||
{id:'examples/colorsprites.a', chapter:8, name:'Color Sprites'},
|
||||
{id:'examples/timing2.a', chapter:9, name:'Fine Positioning', title:'Fine Position'},
|
||||
{id:'examples/missiles.a', chapter:10, name:'Player/Missile Graphics', title:'Player/Missile'},
|
||||
{id:'examples/sethorizpos.a', chapter:11, name:'SetHorizPos Routine'},
|
||||
{id:'examples/piatimer.a', chapter:12, name:'PIA Timer'},
|
||||
{id:'examples/controls.a', chapter:13, name:'Joysticks'},
|
||||
{id:'examples/complexscene.a', chapter:15, name:'Complex Scene I'},
|
||||
{id:'examples/complexscene2.a', chapter:16, name:'Complex Scene II'},
|
||||
{id:'examples/scoreboard.a', chapter:18, name:'Scoreboard'},
|
||||
|
Loading…
x
Reference in New Issue
Block a user