|
Subject: [stella] Pattern Processor code help From: Wade Brown <wbrown@xxxxxxxxxxxxx> Date: Fri, 09 May 2003 05:13:57 -0400 |
;-----------------------------------------------
; test-missile.asm
;
; compile with Dasm 2.12.4
;
; Wade Brown 2001, 2002
;-----------------------------------------------
processor 6502
include vcs.h
;-----------------------------------------------
; Equates
; Note : 76 cycles/scanline
; 228 color clocks/scanline
; Each Line - 68 pixels of H. Blank followed by 160 Visible pixels
; vblank = 37 scanlines
; overscan = 30 scanlines
;-----------------------------------------------
T64_VBLANK EQU 43 ; 43 * 64 = 2752 cycles (vblank= (76 * 37 = 2812 cycles))
T64_OSCAN EQU 35 ; 35 * 64 = 2240 cycles (oscan = (76 * 30 = 2280 cycles))
;------------------------------------------------
; ROM definitions
;------------------------------------------------
RomStart equ $F000
RomEnd equ $FFFF
IntVectors equ $FFFA
;------------------------------------------------
; Screen X,Y Boundaries
; Y ranges from 192 - 1
; X ranges from 0 to 159
;------------------------------------------------
Y_MAX EQU 192
Y_MIN EQU 8
X_MAX EQU 150
X_MIN EQU 0
TOP_LINE EQU 192
;------------------------------------------------
; Object Boundaries - used in ROM InitialPos table
;------------------------------------------------
SHIP_X_MIN EQU 0
ENEMY_X_MIN EQU 0
SHIP_Y_MIN EQU 40
ENEMY_Y_MIN EQU 40
SHIP_X_MAX EQU 153
ENEMY_X_MAX EQU 153
SHIP_Y_MAX EQU 24
ENEMY_Y_MAX EQU 192
;
ENEMY_HEIGHT EQU 16
;------------------------------------------------
; Object Colors (?)
;------------------------------------------------
BG_COLOR EQU $A5 ; blue from 6 to A
ENEMY_COLOR EQU $D0 ; Green from B, D
SHIP_COLOR EQU $32 ; red from 20, 40
;-----------------------------------------------
; Macros
; (<#PatDocileBeg - <#EnemyPatTable)-1
;-----------------------------------------------
mac WAIT_TIMER
.1 LDA INTIM ;Wait for the proper scan line
BNE .1
endm
mac Test
#00
endm
;-----------------------------------------------
; Ram Segment (128 bytes)
;-----------------------------------------------
SEG.U vars
org $80
;-----------------------------------------------
; Game Variables
;-----------------------------------------------
GameVars ; Set X register to this address and jmp to WarmStart
EnemyX DS 1 ; p0
ShipX DS 1 ; p1
EnemyY DS 1
ShipY DS 1
;
; pattern processor variables
;
PatFrame DS 1
PatIndex DS 1
NextIndex DS 1
;
; multi-sprite variables
;
EnemySConf DS 1
MxPos DS 1
;-----------------------------------------------
FrameCount DS 1
Temp DS 1
Temp1 DS 1
;-----------------------------------------------
; Code Start
;-----------------------------------------------
;----------------------------------------------
; <BoilerPlate>
;----------------------------------------------
SEG code
org RomStart
;-----------------------------------------------
; Reset console RAM, TIA registers
;-----------------------------------------------
ResetEntry
SEI
CLD
LDX #$FF
TXS
WarmStart ; set X to start location of memory to clear (i.e GameVars)
LDA #0
.Clear
STA $00,X ; clears memory from location x to location 1 (Does not clear VSYNC at
; address 0)
DEX
BNE .Clear
;----------------------------------------------
; </BoilerPlate>
;----------------------------------------------
JSR GameInit
;-----------------------------------------------
; Main Loop Start
;-----------------------------------------------
MainLoop
JSR VerticalSync ;
JSR VerticalBlank ;
JSR MainScreen ; MainScreen does Overscan
JMP MainLoop ; Repeat
;***********************************************
; Subs
;***********************************************
;-----------------------------------------------
; VSYNC Handler
;-----------------------------------------------
;----------------------------------------------
; <BoilerPlate>
;----------------------------------------------
VerticalSync SUBROUTINE
LDA #$02 ;
STA WSYNC ; Finish current line
STA VSYNC ; start vertical sync
LDA #$03 ;
STA TIM64T ;
JMP WaitIntimReady ; Wait until vertical sync finished
;----------------------------------------------
; </BoilerPlate>
;----------------------------------------------
;-----------------------------------------------
; Vblank handler
;-----------------------------------------------
;----------------------------------------------
; <BoilerPlate>
;----------------------------------------------
VerticalBlank SUBROUTINE
; A =0
STA WSYNC ; Finish current line
STA VSYNC ; Stop vertical sync
LDA #$02 ;
STA VBLANK ; Start vertical blank
LDA #T64_VBLANK ; 43 * 64 = 2752 cycles (vblank= (76 * 37 = 2812 cycles))
STA TIM64T ; Init timer
;----------------------------------------------
; </BoilerPlate>
;----------------------------------------------
LDA FrameCount
JSR SetNewState
LDY #00
JSR ProcPattern
;----------------------------------------------
; Position p0
;----------------------------------------------
LDY #0
LDX EnemyX
JSR PosPlayer
;----------------------------------------------
; <BoilerPlate>
;----------------------------------------------
WaitIntimReady
LDA INTIM ; Wait until vertical blank finished
BNE WaitIntimReady ;
RTS
;----------------------------------------------
; </BoilerPlate>
;----------------------------------------------
;-----------------------------------------------
; Main Screen
;-----------------------------------------------
;----------------------------------------------
; <BoilerPlate>
;----------------------------------------------
MainScreen SUBROUTINE
STA WSYNC ; Finish current line
STA VBLANK ; Stop vertical blank
LDY #192 ; 192 Scanlines
;----------------------------------------------
; </BoilerPlate>
;----------------------------------------------
INC FrameCount
; Set Background Color
LDA #BG_COLOR
STA COLUBK
;
LDA #ENEMY_COLOR
STA COLUP0
nextLine
STA WSYNC
TYA
SBC EnemyY ; a = Line - EnemyY
ADC #ENEMY_HEIGHT ; a = a +
BCC SkipDraw ;
TAX ; get the grIndex in X
LDA GrEscort,X
.byte $2c
SkipDraw
LDA #$00
STA GRP0
;----------------------------------------------
; <BoilerPlate>
;----------------------------------------------
DEY
BNE nextLine
; Screen Finished, disable video and set the oscan timer
LDA #2
STA WSYNC ;Finish this scanline.
STA VBLANK ; video OFF (important)
LDA #T64_OSCAN ; total number of cycles for 30 scan-line OverScan period
STA TIM64T ;Set the timer for start of screen
;----------------------------------------------
; </BoilerPlate>
;----------------------------------------------
;-----------------------------------------------
; overscan handler
;-----------------------------------------------
JSR joy ; get joystick input
;----------------------------------------------
; <BoilerPlate>
;----------------------------------------------
WAIT_TIMER
RTS
;----------------------------------------------
; </BoilerPlate>
;----------------------------------------------
;-----------------------------------------------
; GameInit
;-----------------------------------------------
GameInit SUBROUTINE
;-----------------------------------------------
; Initial object positions, etcetera
;-----------------------------------------------
LDY #3
LoadPosTop
LDA InitialPos,Y
STA EnemyX,Y
DEY
BPL LoadPosTop
;INY
STY PatIndex ; init to $ff
INY
STY PatFrame
RTS
;-----------------------------------------------
; joystick reading
;-----------------------------------------------
joy SUBROUTINE
nop
RTS
;-----------------------------------------------
; Player positionning
; x = xpos
; y = 0 for p0, 1 for p1
;-----------------------------------------------
PosPlayer SUBROUTINE
sta WSYNC ;begin scanline
lda HorzTable,X ;+4 7
sta HMP0,Y ;+3 10
and #$0F ;+2 12
tax ;+2 14
P0
dex ;+2 16
bpl P0 ;when branch not taken: +2 (18 + x*5)
sta RESP0,Y ;(21 + x*5)
sta WSYNC
sta HMOVE
rts
;-----------------------------------------------
; Pattern Byte processing
;-----------------------------------------------
;-----------------------------------------------
; Process Pattern
;-----------------------------------------------
; PatByte Layout:
; d7-d6: frames
; d5-d3: x offset
; d0-d2: y offset
; Note for x and y offset if high bit (d5 for x, d2 for y) set then it is negative offset
; in 2's complement form....
;
ProcPattern
JSR GetPatByte
LDX #2
JSR StorePatVal
; x offset
TYA ; patbyte in A
LSR
LSR
LSR ; shift into low order bits
LDX #0 ; for x values
JSR StorePatVal ;
RTS
;
; OUT: A, Y set to pat byte contents
GetPatByte
;
LDX PatIndex
NextByte
LDY PatFrame
BNE NextFrame
; if (PatFrame == 0) {
; get next pattern byte
INX
STX PatIndex ; inc pat index
; get patbyte
LDA EnemyPatTable,X
BEQ ResetPattern ; jump if sentinel end of pattern byte (0)
; get/set new PatFrame
AND #$C0
CLC
ROL
ROL
ROL
STA PatFrame
NextFrame
DEC PatFrame
LDA EnemyPatTable,X
BEQ ResetPattern
TAY
RTS
ResetPattern
TAX
DEX
STX PatIndex
STA PatFrame
BCS NextByte ; ALWAYS Taken
;-----------------------------------------------
; StorePatVal
; A = patbyte
; x = 0 for x, 2 for y
;-----------------------------------------------
StorePatVal
STX Temp1 ; save X
AND #$07 ; mask all but lower three bits (y)
BIT NegMask ;
BEQ NoNeg ; neg bit set
ORA #$F8 ; flip top 5 bits to 1
NoNeg ; positive y offset
LDX Temp1 ; restore X
STA Temp ; motion offset
LDA EnemyX,X ; current pos
CLC
ADC Temp ; calc new value
STA EnemyX,X ; store new pos
RTS ;
;
; In: randomized value in A
; gets new PatIndex in
SetNewState SUBROUTINE
; AND #$07
; TAX
; LDA PatIndexTable,X
; STA NextIndex
RTS
;-----------------------------------------------
; Graphics Start
;-----------------------------------------------
GrPage ALIGN 256
;
; Alien "Escort" (16 bytes)
;
GrEscort
.byte %10000001 ; X......X
.byte %10000001 ; X......X
.byte %01011010 ; .X.XX.X.
.byte %00111100 ; ..XXXX..
.byte %10111101 ; X.XXXX.X
.byte %01100110 ; .XX..XX.
.byte %01111110 ; .XXXXXX.
.byte %11111111 ; XXXXXXXX
.byte %11111111 ; XXXXXXXX
.byte %10111101 ; X.XXXX.X
.byte %11111111 ; XXXXXXXX
.byte %11111111 ; XXXXXXXX
.byte %01111110 ; .XXXXXX.
.byte %00111100 ; ..XXXX..
.byte %01000010 ; .X....X.
.byte %10000001 ; X......X
;
;
;
GrEscort1
.byte %01000010 ; .X....X.
.byte %10000001 ; X......X
.byte %01011010 ; .X.XX.X.
.byte %00111100 ; ..XXXX..
.byte %00111100 ; ..XXXX..
.byte %11100111 ; XXX..XXX
.byte %01100110 ; .XX..XX.
.byte %11111111 ; XXXXXXXX
.byte %11111111 ; XXXXXXXX
.byte %10111101 ; X.XXXX.X
.byte %11111111 ; XXXXXXXX
.byte %11111111 ; XXXXXXXX
.byte %01111110 ; .XXXXXX.
.byte %00111100 ; ..XXXX..
.byte %01000010 ; .X....X.
.byte %01000010 ; .X....X.
;
; Player (12 bytes)
;
GrShip
.byte %10011001 ; 1..11..1
.byte %11100111 ; 111..111
.byte %11000011 ; 11....11
.byte %11000011 ; 11....11
.byte %11000011 ; 11....11
.byte %11000011 ; 11....11
.byte %11000011 ; 11....11
.byte %11000011 ; 11....11
.byte %11100111 ; 111..111
.byte %10011001 ; 1..11..1
.byte %00011000 ; ...11...
.byte %00011000 ; ...11...
;
; 256 bytes for variables
;
VarsPage ALIGN 256
;------------------------------------------------------------------------
; Horz Motion Values: works from 0 to screen edge
; From Manuel Polik's Gunfight
;------------------------------------------------------------------------
HorzTable ;this must not cross a page boundary
.byte $30,$20,$10,$00,$F0,$E0,$D0,$C0,$B0,$A0,$90
.byte $71,$61,$51,$41,$31,$21,$11,$01,$F1,$E1,$D1,$C1,$B1,$A1,$91
.byte $72,$62,$52,$42,$32,$22,$12,$02,$F2,$E2,$D2,$C2,$B2,$A2,$92
.byte $73,$63,$53,$43,$33,$23,$13,$03,$F3,$E3,$D3,$C3,$B3,$A3,$93
.byte $74,$64,$54,$44,$34,$24,$14,$04,$F4,$E4,$D4,$C4,$B4,$A4,$94
.byte $75,$65,$55,$45,$35,$25,$15,$05,$F5,$E5,$D5,$C5,$B5,$A5,$95
.byte $76,$66,$56,$46,$36,$26,$16,$06,$F6,$E6,$D6,$C6,$B6,$A6,$96
.byte $77,$67,$57,$47,$37,$27,$17,$07,$F7,$E7,$D7,$C7,$B7,$A7,$97
.byte $78,$68,$58,$48,$38,$28,$18,$08,$F8,$E8,$D8,$C8,$B8,$A8,$98
.byte $79,$69,$59,$49,$39,$29,$19,$09,$F9,$E9,$D9,$C9,$B9,$A9,$99
.byte $7A,$6A,$5A,$4A,$3A,$2A,$1A,$0A,$FA,$EA,$DA,$CA,$BA,$AA,$9A
;
; Piero Cavina's multi-sprite tables....
newconftable .byte $4, $0, $0, $1
.byte $FF, $0, $FF, $2
.byte $FF, $FF, $0, $1
offsettable .byte $0, $10, $20, $10
.byte $FF, $0, $FF, $0
.byte $FF, $FF, $0, $0
;------------------------------------------------------------------------
;
;
;------------------------------------------------------------------------
VarsPage1 Align 256
; Initial Object Positions
; EnemyX, ShipX, EnemyY,ShipY
InitialPos
.byte #80, #80, #160, #SHIP_Y_MIN
;
; Docile, Warm
; Attack, Attack1
; Retreat, Retreat1
; Docile, Attack
PatIndexTable
.BYTE #(<PatDocileBeg-<EnemyPatTable), #(<PatWarmBeg-<EnemyPatTable), #(<PatAttackBeg-<EnemyPatTable), #(<PatWarmBeg-<EnemyPatTable)
.byte #(<PatAttackBeg-<EnemyPatTable), #(<PatAttack1Beg-<EnemyPatTable), #(<PatAttackBeg-<EnemyPatTable), #(<PatAttack1Beg-<EnemyPatTable)
;------------------------------------------------------------------------
;Object Colors
; Enemy, Ship
;------------------------------------------------------------------------
ObjColorTab
.byte #ENEMY_COLOR, #ENEMY_COLOR, #ENEMY_COLOR, #ENEMY_COLOR, #ENEMY_COLOR, #ENEMY_COLOR, #ENEMY_COLOR, #ENEMY_COLOR
.byte #SHIP_COLOR, #SHIP_COLOR, #SHIP_COLOR, #SHIP_COLOR, #SHIP_COLOR, #SHIP_COLOR, #SHIP_COLOR, #SHIP_COLOR
; PatByte Layout:
; d7-d6: frames
; d5-d3: x offset
; d0-d2: y offset
; Note for x and y offset if high bit (d5 for x, d2 for y) set then it is negative offset
; in 2's complement form....
;
EnemyPatTable
; $c4, $c4, $c8, $d8, $c1, $c2
; 111 (-1), 110 (-2), 101 (-3), 100 (-4)
PatDocileBeg ; Loose Circles
; 4 x+,y0 4 x+, y0 4 x+,y- 4 x+,y- 4 x0,y- 4 x0,y- 4 x-,y- 4 x-,y-
.BYTE %11001000,%11001000, %11001111,%11001111, %11000111,%11000111, %11111111, %11111111
; 4 x-,y0 4 x-,y0 4 x-,y+ 4 x-,y+ 4 x0,y+ 4 x0,y+ 4 x+,y+ 4 x+,y+
.BYTE %11111000,%11111000, %11111001,%11111001, %11000001,%11000001, %11001001, %11001001, $00
PatDocileEnd
;
PatWarmBeg ; Tight Circles
; %11001111, %11000111, %11111111
;.BYTE %11111000, %11111001, %11000001, %11001001, $00
PatWarmEnd
;
PatAttackBeg
.BYTE %11111110, %11000101, %11001100, $00
PatAttackEnd
;
PatAttack1Beg
.BYTE %10111110, %10000101, %11011110, %11000100, %11011111, $00
PatAttack1End
;
PatRetreatBeg
.BYTE %11001011, %11011010, %1110001, $00
PatRetreatEnd
;
PatRetreat1Beg
.BYTE %11001011, %11001011, %01011010, %1110001, $00
PatRetreat1End
;
;
NegMask HEX 04
DiffSwitchTbl HEX 4080 ;Left,Right difficulty flags
ORG IntVectors
NMI .word ResetEntry
Reset .word ResetEntry
Irq .word ResetEntry
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| [stella] Stella emulation errors wi, Dennis Debro | Thread | Re: [stella] Pattern Processor code, Andrew Davie |
| Re: [stella] A warning to newbies -, Christopher Tumber | Date | Re: [stella] Pattern Processor code, Andrew Davie |
| Month |