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 |