|
Subject: [stella] Unending VDEL hell From: Glenn Saunders <cybpunks2@xxxxxxxxxxxxx> Date: Mon, 29 Apr 2002 00:49:38 -0700 |
Glenn Saunders - Producer - Cyberpunks Entertainment Personal homepage: http://www.geocities.com/Hollywood/1698 Cyberpunks Entertainment: http://cyberpunks.uni.cc
;Death Derby 2002
; By Glenn Saunders
;LINEAGE:
; How to Draw an Asymmetric Reflected Playfield
; by Roger Williams
; with a lot of help from Nick Bensema
; (this started out as his "How to Draw a Playfield")
; Extra help from Thomas Jentzsch
processor 6502
include vcs.h
; CONSTANTS
; SCREEN GEOMETRY CTR ACTUAL SUBTOTAL
;----------------------- ---- --------- --------
ScoreHeight = 20; 20 20
; TopBorder = 2 2 22
PlayfieldHeight = 88; (176) 198
; BottomBorder = 2 2 200
; ---
; 200 visible lines
OverScanHeight = 22; 22 222
; ---
; 222 total lines
;FIXED COLORS
Color0 = $34
Color1 = $C8
ColorPF = $0F;White
ColorSafeZone = $1E;Yellow
;INITIAL COUNTER VALUES
TombstoneHeight = 8 ; 8*2 = 16 (single scanlines) high per tombstone
TombstoneRowsPerScreen = 11-1 ; 11 rows of tombstones per screen
CarHeight = 8-1 ; 8 doubled scanlines (used as offset)
; constants that reference rotation index pointers
PointUp = 0
PointRight = 4
PointDown = 8
PointLeft = 12
TurnOnSpriteReflect = %00001000
TurnOffSpriteReflect = 0
CarPage = $FF;00
CarDataAlign = $65
InitialSafeZone = %10010000 ; initial safezone border graphics
SafeZone2 = %10000000
FlipThreshold = #9 ; flip sprite when
;P0_CurrentRotationIndex >= 9
SEG.U vars
org $80
;TEMPORARY VARIABLES (OVERLAYS)
Temp ds 1
LastController_temp_State = Temp
Temp2 ds 1
CurrentControllerState = Temp2
Compensate ds 1; determines whether to compensate for VDEL
P0_P1_PARAMETER ds 1
;CurrentScanLine ds 1
; use Y instead
;CurrentTombstoneRow ds 1; 11->0 outer loop counter
; use X instead
CurrentTombstoneSubRow ds 1; 7->0 inner loop counter
; ALTERNATING SAFEZONE BORDER STRIP
CurrentSafeZone ds 1
; PLAYFIELD BITMAP
PF1DataRAM ds TombstoneRowsPerScreen+1
PF2DataRAM ds TombstoneRowsPerScreen+1
PF1bDataRAM ds TombstoneRowsPerScreen+1
PF2bDataRAM ds TombstoneRowsPerScreen+1
;sprite positiong
P0_Y ds 1
P1_Y ds 1
P0_X ds 1
P1_X ds 1
P0_YFullres ds 1
P1_YFullres ds 1
M0_Y ds 1
M1_Y ds 1
M0_X ds 1
M1_X ds 1
FrameCounter1 ds 1; use this for timing purposes
;sprite graphics pointers
P0_CurrentRotationSequence ds 1; 0-15
P1_CurrentRotationSequence ds 1; 0-15
;these above reference addresses that get stored below
P0_CurrentFramePtr ds 2; this will wind up being a constant $FF in the high byte
P1_CurrentFramePtr ds 2; this will wind up being a constant $FF in the high byte
M0_CurrentFramePtr ds 2
M1_CurrentFramePtr ds 2
LastControllerState ds 1; store previous state of the controller ports
;CurrentController_P0_State ds 1
;P0_CurrentRowCounter ds 1
;P1_CurrentRowCounter ds 1
;M0_CurrentRowCounter ds 1
;M1_CurrentRowCounter ds 1
; stolen from OUTLAW source
;PF0Array ds 1 ; PF0 array, 18 Bytes
;ScoreshapeLow01 ds 1 ; Shape of player 1 lower score digit
;ScoreshapeLow02 ds 1 ; Shape of player 2 lower score digit
;ScoreshapeHi01 ds 1 ; Shape of player 1 higher score digit
;ScoreshapeHi02 ds 1 ; Shape of player 2 higher score digit
;bcdScore01Backup ds 1 ; Backups score for player 1
;rightScoreOnOff ds 1 ; 0F for Right score on, 00 for off
gameState ds 1 ; 0F running/EF saver/00 select/XX counter
SEG code
org $F000
;FrameCounter = $93 was going to try some color cycling
; BRANCH CHEAT SHEET
;
; opcode flags integer type
;======= =============== =============== ============
;A == M BEQ N=0, Z=1, C=1
;A != M BNE N=?, Z=0, C=?
;A >= M BCS N=?, Z=?, C=1 (unsigned)
;A > M BCS and BNE N=?, Z=?, C=1 (unsigned)
;A < M BCC N=?, Z=0, C=0 (unsigned)
;A >= M BPL N=0,;Z=?, C=? (signed)
;A > M BPL and BNE N=0,;Z=0, C=? (signed)
;A < M BMI N=1;;Z=0; C=? (signed)
Start
SEI ; Disable interrupts, if there are any.
CLD ; Clear BCD math bit.
LDX #$FF
TXS ; Set stack to beginning.
; CLEAR OUT RAM
LDA #0
KeepZeroing
STA 0,X
DEX
BNE KeepZeroing
SetColors
LDA #$00
STA COLUBK ; Background will be black.
LDA #ColorPF
STA COLUPF
LDA #PF_Reflect
STA CTRLPF ; set playfield to reflect
LDA #Color0
STA COLUP0
LDA #Color1
STA COLUP1
LDA #60
STA FrameCounter1
InitializeControllerState
LDA #0
STA SWACNT; set controller ports for input first
InitializeSprites
; set high byte for frame pointers
; this should only have to be done once for the whole game
; since all the car graphics are on the same page of ROM
LDA #CarPage; $FF
STA P0_CurrentFramePtr+1
STA P1_CurrentFramePtr+1
;LDA #0
;STA Compensate
; set initial X,Y of P0, P1
LDA #27; start P0 +10 from the left
STA P0_X
LDA #94; start P0 halfway down
STA P0_YFullres
SEC
SBC Compensate
LSR
STA P0_Y
;LDA #127; start P1 -10 the right
LDA #27
STA P1_X
LDA #94; start P1 halfway down
STA P1_YFullres
LSR
STA P1_Y
; set initial rotations
LDX #PointRight; start P0 car pointing right
STX P0_CurrentRotationSequence; store for later
LDX #PointLeft; start P1 car pointing left
STX P1_CurrentRotationSequence; store for later
LDX #TombstoneRowsPerScreen
InitializeTombstones; copy from ROM to RAM
LDA #InitialSafeZone
STA CurrentSafeZone
LDA PF1Data,X
STA PF1DataRAM,X
LDA PF2Data,X
STA PF2DataRAM,X
LDA PF1bData,X
STA PF1bDataRAM,X
LDA PF2bData,X
STA PF2bDataRAM,X
DEX
BPL InitializeTombstones
InitializeControllerParse
LDA SWCHA; read ports once
STA CurrentControllerState; store to temp variable
STA LastControllerState
MainLoop
JSR VerticalBlank
JSR GameCalc
JSR DrawScreen
JSR OverScan
JMP MainLoop ;Continue forever.
ReadController1
LDA CurrentControllerState
AND %00000011
TAY
LDA LastControllerState
AND %00000011
STA LastController_temp_State
CPY LastController_temp_State; see if there was no change
BNE .Merge1
RTS
.Merge1
ASL
ASL ; move it over two to the left
STA LastController_temp_State
TYA
ORA LastController_temp_State; merge
TAY
JMP .MainParse
ReadController0
LDA CurrentControllerState
AND %00111111
;DO CONTROLLER 0 FIRST
LSR
LSR
LSR
LSR; move the 4 bits of P0 data over
;AND %00000011
TAY ; move it out of the way
; Y will hold the current controller state
; A or LastController_temp_State will hold previous controller state
LDA LastControllerState
AND %00111111
LSR
LSR
LSR
LSR; move the 4 bits of P0 data over
STA LastController_temp_State; temp variable
; test for no change
CPY LastController_temp_State; see if there was no change
BNE .Merge0
RTS
.Merge0
ASL
ASL ; move it back over two to the left
STA LastController_temp_State
TYA
ORA LastController_temp_State; merge
TAY
.MainParse:
; scan through both tables.
LDX #7
TYA
.KeepScanning:
CMP EncodingTable,X
BEQ .PickDirection
DEX
BPL .KeepScanning
;abrupt twist because no match
RTS
.PickDirection:
CLC
CPX #4
BCS .FoundCurrentMatchRight; if X >= 4 then turning right
;else left
.FoundCurrentMatchLeft:
LDX P0_P1_PARAMETER
;LDX #0
; decrement rotation counter and exit
LDA P0_CurrentRotationSequence,X
; else decrement
CMP #0
BEQ .SetHigh; if A = 0 then set loop back to 15
DEC P0_CurrentRotationSequence,X; else go ahead and decrement
RTS
.SetHigh
LDA #15
STA P0_CurrentRotationSequence,X
RTS
.FoundCurrentMatchRight
LDX P0_P1_PARAMETER
;LDX #0
; decrement rotation counter and exit
LDA P0_CurrentRotationSequence,X
; else decrement
CMP #15
BEQ .SetLow; if A = 0 then set loop back to 15
INC P0_CurrentRotationSequence,X; else go ahead and decrement
RTS
.SetLow
LDA #0
STA P0_CurrentRotationSequence,X
RTS
; end of controller check
VerticalBlank
LDX #0
LDA #2
STA WSYNC
STA WSYNC
STA WSYNC
STA VSYNC ; Begin vertical sync.
STA WSYNC ; First line of VSYNC
STA WSYNC ; Second line of VSYNC.
LDA #44
STA TIM64T
LDA #0
STA CXCLR
STA WSYNC ; Third line of VSYNC.
STA VSYNC ; (0)
RTS
;SUB
ClearTombstones
LDX #TombstoneRowsPerScreen
KeepClearing
DEX
STA <PF1DataRAM,X
STA <PF2DataRAM,X
STA <PF1bDataRAM,X
STA <PF2bDataRAM,X
BNE KeepClearing
RTS
;SUB
OverScan
LDX #OverScanHeight
.KillLines
STA WSYNC
DEX
BNE .KillLines
RTS
;HORIZONTAL POSITIONING SUBROUTINE FROM MANUEL POLIK's GUNFIGHT
;SUB (alternate beginning of below)
PosP1
CLC
ADC #$00; changed from 08
;SUB
PosP0
CMP #$A0
BCC .NH2
SBC #$A0
.NH2
TAY
LSR
LSR
LSR
LSR
STA Temp
TYA
AND #15
CLC
ADC Temp
LDY Temp
CMP #15
BCC .NH
SBC #15
INY
.NH
EOR #7
ASL
ASL
ASL
ASL
STA HMP0,X
INY ; Waste 5 cycles, 1 Byte
STA WSYNC
INY ; Waste 7(!) cycles, 1 Byte
BIT 0 ; Waste 3 cycles, 2 Byte
.PosDelay DEY
BPL .PosDelay
STA RESP0,X
RTS
;/HORIZONTAL POSITIONING SUBROUTINE
;this will have been modified by the controller routines
UpdateCurrentFramePtr
LDY #TurnOffSpriteReflect; initialize to no flip
LDX P0_P1_PARAMETER
;this will load either P0 or P1 depending on P0_P1_PARAMETER
LDA P0_CurrentRotationSequence,X;0-15
TAX
CPX #FlipThreshold
BMI .Continue0 ; if A < 9 then sigN will be 1
; so do not flip, just .Continue
.FlipSprite0
LDY #TurnOnSpriteReflect
.Continue0
STX Temp
;THIS WILL STORE TO P0 or P1 depending on P0_P1_PARAMETER
LDX P0_P1_PARAMETER
STY REFP0,X
LDX Temp
; load low byte pointer to the start
; of gfx for the current frame
LDA RotationSequence,X
SEC ; set carry bit
LDX P0_P1_PARAMETER
SBC P0_Y,X; subtract the Y position of P0 or P1
ADC #CarHeight
; POINTER is initialized as offset -PO_Y away from the last scanline
; of CarRotation0 graphics.
; STORE THE LOW BYTE POINTER
TAY; get RotationSequence out of the way
;THIS WILL STORE TO P0 or P1 depending on P0_P1_PARAMETER
LDA P0_P1_PARAMETER
ASL ; multiply by 2, yielding either 0 or 2
TAX ; use as an offset index
TYA; restore RotationSequence
STA P0_CurrentFramePtr,X
RTS
;SUB
GameCalc
;BRK
DEC FrameCounter1
BNE .NoMove
LDA #60
STA FrameCounter1
INC P0_YFullres
INC P1_YFullres
.NoMove
LDX #0 ; store to HMP0
LDA P0_X; load current X value of P0
JSR PosP0; call coarse pos calc routine for P0
LDA #2
STA WSYNC
LDX #1; store to HMP1
LDA P1_X; load current X value of P1
JSR PosP1; call coarse pos calc routine for P1
LDA #2
STA WSYNC
STA HMOVE
;later on we need to add the horizontal positioning
;of the two missiles
LDA P0_YFullres
LSR
;SEC
;SBC #1
STA P0_Y
LDA P1_YFullres
LSR
STA P1_Y
; LDA P1_YFullres
; TAX
; EOR #1
; BEQ .NoCompensation
; TXA
; SEC
; SBC #1
; LSR
; JMP .SetY
;.NoCompensation
; TXA
; LSR
;.SetY
; STA P1_Y
; NOW ON : ODD
;assume that car 0 is on the same line with car 1, when it's
;P0_YFullres is *one* below P1_YFullres.'
;----CAR0--------------
;------------------CAR1
;IF Y = EVEN (for both cars)
; NO COMPENSATION
;-> VDELP0 = 1
;-> VDELP1 = 0
;IF Y = ODD (for both cars)
; P0_Y = P0_Y + 1 (compensate)
;-> VDELP0 = 0
;-> VDELP1 = 1
LDA P0_YFullres ;of player position
EOR #1
; IF ODD,THEN VDEL
BNE .SetVDELP0
LDA 1
JMP .ClearVDELP0
.SetVDELP0
LDA 0
.ClearVDELP0
STA VDELP0
LDA P1_YFullres ;of player position
EOR #1
BNE .SetVDELP1
LDA 0
JMP .ClearVDELP1
.SetVDELP1
LDA 1
.ClearVDELP1
STA VDELP1
LDA SWCHA; read ports once
STA CurrentControllerState; store to temp variable
LDA #0
STA P0_P1_PARAMETER
;JSR ApplyMotion
JSR ReadController0
JSR UpdateCurrentFramePtr
LDA #1
STA P0_P1_PARAMETER
;JSR ApplyMotion
JSR ReadController1
JSR UpdateCurrentFramePtr
LDA CurrentControllerState; read back stored ports
STA LastControllerState; store for next time
RTS
;END GAMECALC
DrawScreen
LDA INTIM
BNE DrawScreen ; FINISH WAITING OUT GAMECALC AND THEN DRAW
STA WSYNC
STA VBLANK ;End the VBLANK period with a zero.
LDA #0
STA PF0
STA PF1
STA PF2; zero out playfield
; reset fine-control on sprites so that they don't get
; repositioned with the missiles
STA HMP0
STA HMP1
LDX #ScoreHeight; burn through 20 total scanlines
DrawScore
STA WSYNC
DEX
BNE DrawScore
TopBorder ; 2 lines
LDA #$FF
STA PF0 ; draw a solid line
STA PF1
STA PF2
LDA #InitialSafeZone
STA WSYNC
; draw a solid line except for the safezone border
STA PF0
;ScanGo will finish the line off
FinalInitialization
;INITIALIZE TOMBSTONE ROW COUNTERS
LDX #TombstoneRowsPerScreen+1
;TombstoneRowsPerScreen held in X register through kernel
LDA #TombstoneHeight+1
; NOTE: pad these by one because the first time through it decrements
; at the top of the loop
STA CurrentTombstoneSubRow; store TombstoneHeight to RAM
LDY #PlayfieldHeight ; store scanline counter in Y throughout
; the whole kernel. Decrement every other scanline
;THIS AREA IS A 2-LINE KERNEL
;START FIRST LINE OF LINE-PAIR
ScanLoop1
;INNER LOOP
DEC CurrentTombstoneSubRow ;next row of current tombstone
BNE ScanGo1
LDA #TombstoneHeight; if counter reaches zero, reset to 7
STA CurrentTombstoneSubRow; and store back to RAM
DEX ;CurrentTombstoneRow = CurrentTombstoneRow - 1
;outer loop - indexes next tombstone row
ScanGo1
TYA ;+2
SEC ;+2
SBC P0_Y ;+3
ADC #CarHeight+1 ;+2
BCS .drawP0 ;+2/+3
LDA #0 ;+2
BEQ .setP0 ;+3
.drawP0:
LDA (P0_CurrentFramePtr),Y ; +5
.setP0:
;MAX 20 cycles
STA WSYNC
STA.W GRP0 ;+3
; Time to begin cycle counting
; 0
;STA HMOVE ;+4 4
; in order for a proper 2-line kernel w/VDEL to operate properly,
; it is necessary to write to GRP0 on the first of the two line-pairs
; right after WSYNC. You can then update GRP1 at any time between then
; and the end of the 2nd line-pair.
STA GRP0 ;+3
;will probably have to do an HMOVE on every line to
;simplify logic. HMOVE is only necessary for the missiles
LDA <PF1DataRAM-1,X ;+4 8
;I'm not sure why the -1 is necessary here to make it work
STA PF1 ;+3 = *11* < 29 ;PF1 visible
LDA <PF2DataRAM-1,X ;+4 15
STA.W PF2 ;+3 = *19* < 40 ;PF2 visible
;NOP
NOP ;+2 20
NOP ;+2 22
NOP ;+2 24
NOP ;+2 26
NOP ;+2 28
NOP ;+2 30
NOP ;+2 32
;NOP ;+2 34
LDA <PF1bDataRAM-1,X ;+4 38
;PF1 no longer visible, safe to rewrite
STA PF1 ;+3 = *41*
LDA <PF2bDataRAM-1,X ;+3 44
;PF2 rewrite must begin at exactly cycle 45!!, no more, no less
STA PF2 ;+3 = *47* ; > 46 PF2 no longer visible
;TXS ;+2 49
STX Temp
NOP ;+2 51
;preserve X register
NOP ;+2 53
NOP ;+2 55
NOP ;+2 57
NOP ;+2 59
NOP ;+2 61
NOP ;+2 63
;NOP ;+2 65
;NOP ;+2 67
LDA #0 ;+2 69
; CLEAR OUT PLAYFIELD FOR SPRITE HANDLING BELOW
STA PF2 ;+3 72
STA PF1 ;+3 75
STA HMP0 ;+3
STA HMP1 ;+3
STA HMOVE ;+4 4
;PERFECT TIMING, NO WSYNC NECESSARY
; PUT ONE BACK IN IF THE NOPs are replaced with code
; that has varying timing
;START SECOND LINE OF LINE-PAIR
ScanGo2 ; do all the sprite routines here
; WSYNC PUT BACK IN IF NECESSARY
; start cycle counting again
; 0
P1Loop
TYA ;+2
SEC ;+2
SBC P1_Y ;+3
ADC #CarHeight+1 ;+2
BCS .drawP1 ;+2/+3
LDA #0 ;+2
BEQ .setP1 ;+3
.drawP1:
LDA (P1_CurrentFramePtr),Y
.setP1:
STA GRP1 ;+3
.endLoop
LDX Temp
;TSX; grab tombstone counter back again
DEY ; Decrement ScanlinePair counter
BNE ScanLoop1; keep going until scanline counter reaches 0
DoBorder
LDA #$FF ; this may overload the timing of the sprite kernel line
; and have to be moved under WSYNC!!
STA WSYNC; finish last line of sprites
STA PF0 ; draw a straight line
STA PF1
STA PF2
STA WSYNC; line 1 of bottom border
STA WSYNC; line 2 of bottom border
EndKernel
STA VBLANK ; Make TIA output invisible,
; Y is already zero
STY PF0
STY PF1
STY PF2
STY GRP0
STY GRP1
STY ENAM0
STY ENAM1
STY ENABL
RTS; END DrawScreen
;THE DATA
org $FE00
;stores first 2 bits of quadrature encoding data
;and the expected next set
EncodingTable
;
;RotatingLeft ; RLRL
.byte %00000001
.byte %00000111
.byte %00001110
.byte %00001000; X < 4 = left
;
;RotatingRight ; RLRL; X > 3 = right
.byte %00000010
.byte %00001011
.byte %00001101
.byte %00000100
scoreshapedata:
.byte %01000100 ; | X X |
.byte %10101010 ; |X X X X |
.byte %10101010 ; |X X X X |
.byte %10101010 ; |X X X X |
.byte %01000100 ; | X X |
.byte %11001100 ; |XX XX |
.byte %01000100 ; | X X |
.byte %01000100 ; | X X |
.byte %01000100 ; | X X |
.byte %11101110 ; |XXX XXX |
.byte %11101110 ; |XXX XXX |
.byte %00100010 ; | X X |
.byte %01100110 ; | XX XX |
.byte %10001000 ; |X X |
.byte $11101110 ; |XXX XXX |
.byte %11101110 ; |XXX XXX |
.byte %00100010 ; | X X |
.byte %01000100 ; | X X |
.byte %00100010 ; | X X |
.byte %11001100 ; |XX XX |
.byte %10001000 ; |X X |
.byte %10101010 ; |X X X X |
.byte %11101110 ; |XXX XXX |
.byte %00100010 ; | X X |
.byte %00100010 ; | X X |
.byte %11101110 ; |XXX XXX |
.byte %10001000 ; |X X |
.byte %11001100 ; |XX XX |
.byte %00100010 ; | X X |
.byte %11001100 ; |XX XX |
.byte %01000100 ; | X X |
.byte %10001000 ; |X X |
.byte %11101110 ; |XXX XXX |
.byte %10101010 ; |X X X X |
.byte %11101110 ; |XXX XXX |
.byte %11101110 ; |XXX XXX |
.byte %00100010 ; | X X |
.byte %01000100 ; | X X |
.byte %10001000 ; |X X |
.byte %10001000 ; |X X |
.byte %11101110 ; |XXX XXX |
.byte %10101010 ; |X X X X |
.byte %11101110 ; |XXX XXX |
.byte %10101010 ; |X X X X |
.byte %11101110 ; |XXX XXX |
.byte %11101110 ; |XXX XXX |
.byte %10101010 ; |X X X X |
.byte %11101110 ; |XXX XXX |
.byte %00100010 ; | X X |
.byte %01000100 ; | X X |
org $FF00
; REFLECTED PLAYFIELD
;
; PF0| PF1 | PF2 || PF2b | PF1b |PF0b|
;4567|76543210|01234567||76543210|01234567|7654|
;INITIAL TITLE GRAPHICS
;TO BE COPIED TO RAM
;SafeZone ; 7654----
; .byte %10011001
PF1Data ;D 76543210
.byte %01111001
.byte %01000101
.byte %01000101
.byte %01000101
.byte %01111001
.byte %00000000
.byte %01111001
.byte %01000101
.byte %01000101
.byte %01000101
.byte %01111001
PF2Data ;EA 01234567
.byte %00101111
.byte %10100000
.byte %11100111
.byte %00100000
.byte %11101111
.byte %00000000
.byte %00101111
.byte %00100000
.byte %11100111
.byte %00100000
.byte %11101111
PF2bData ; 76543210;<--- scanning order
.byte %11011110
.byte %00010001
.byte %10011110
.byte %01010001
.byte %10011110
.byte %00000000
.byte %01000100
.byte %01000100
.byte %11000100
.byte %01000100
.byte %11011111
PF1bData; 01234567;<--- scanning order
.byte %00111110
.byte %00100000
.byte %00111110
.byte %00100010
.byte %00100010
.byte %00000000
.byte %00100010
.byte %00100010
.byte %00111110
.byte %00100010
.byte %00100010
; THE ROTATION SEQUENCE POINTERS
; when writing the driving controller code, I will
; index through this table of pointers which rotates
; through the frames. These pointers only store the low byte
; value. The high value is always going to be $FF anyway.
; since the shapes are stored upside down, the actual orientation
; is indicated in the notes. the shapes in the sourcecode will
; appear upside-down
RotationSequence
;NO FLIP BIT - FACE RIGHT
.byte <CarRotation0;0 - point up
.byte <CarRotation1;1 -
.byte <CarRotation2;2 -
.byte <CarRotation3;3 -
.byte <CarRotation4;4 - point right
.byte <CarRotation5;5 -
.byte <CarRotation6;6 -
.byte <CarRotation7;7 -
.byte <CarRotation8;8 - point down
; WITH FlipThreshold - FACE LEFT
.byte <CarRotation7;9 -
.byte <CarRotation6;10 -
.byte <CarRotation5;11 -
.byte <CarRotation4;12 - point left
.byte <CarRotation3;13 -
.byte <CarRotation2;14 -
.byte <CarRotation1;15 -
org $FF00+CarDataAlign
; make sure all sprite graphics are at least 'CarDataAlign' bytes
; above the page in order to make sure that the vertical
; logic routine will work properly
; THIS STORES HALF OF THE ROTATIONS.
; THE OTHER HALF ARE GENERATED BY USING THE HARDWARE PLAYER FLIP FUNCTION
; note that this rotation frame doesn't need an upside down version because it is symmetrical
;9 frames * 8 bytes per frame = 56 bytes used
CarRotation0;UP (ACTUAL)
;.byte %00000000
.byte %01011010; .X.XX.X.
.byte %01111110; .XXXXXX.
.byte %01100110; .XX..XX.
.byte %00011000; ...XX...
.byte %01011010; .X.XX.X.
.byte %01111110; .XXXXXX.
.byte %01011010; .X.XX.X.
.byte %00011000; ...XX...
CarRotation1
;.byte %00000000
.byte %00000110; ....XX..
.byte %00011110; ..XXXX..
.byte %01110100; XXX.X...
.byte %00011010; XX.XX.X.
.byte %00011010; ...XX.X.
.byte %01011111; .X.XXXXX
.byte %00111100; ..XXXX..
.byte %00101100; ..X.XX..
CarRotation2
;.byte %00000000
.byte %00011000; ...XX...
.byte %01111000; .XXXX...
.byte %01000010; .X....X.
.byte %11011011; XX.XX.XX
.byte %11011100; XX.XXX..
.byte %00011110; ...XXXX.
.byte %00110110; ..XX.XX.
.byte %00010000; ...X....
CarRotation3
;.byte %00000000
.byte %00110000; ..XX....
.byte %00110010; ..XX.X..
.byte %01100011; .XX...XX
.byte %01011110; .X.XXXX.
.byte %11111111; XXXXXXXX
.byte %11000111; XX...XXX
.byte %00011100; ...XXX..
.byte %00000100; .....X..
CarRotation4;RIGHT|LEFT
;.byte %00000000
.byte %00000000; ........
.byte %11101110; XXX.XXX.
.byte %01100100; .XX..X..
.byte %11011111; XX.XXXXX
.byte %11011111; XX.XXXXX
.byte %01100100; .XX..X..
.byte %11101110; XXX.XXX.
.byte %00000000; ........
CarRotation5
;.byte %00000000
.byte %00000100; .....X..
.byte %00011100; ...XXX..
.byte %11000111; XX...XXX
.byte %11111111; XXXXXXXX
.byte %01011110; .X.XXXX.
.byte %01100011; .XX...XX
.byte %00110010; ..XX.X..
.byte %00110000; ..XX....
CarRotation6
;.byte %00000000
.byte %00010000; ...X....
.byte %00110110; ..XX.XX.
.byte %00011110; ...XXXX.
.byte %11011100; XX.XXX..
.byte %11011011; XX.XX.XX
.byte %01000010; .X....X.
.byte %01111000; .XXXX...
.byte %00011000; ...XX...
CarRotation7
;.byte %00000000
.byte %00101100; ..X.XX..
.byte %00111100; ..XXXX..
.byte %01011111; .X.XXXXX
.byte %00011010; ...XX.X.
.byte %11011010; XX.XX.X.
.byte %11101000; XXX.X...
.byte %00111100; ..XXXX..
.byte %00001100; ....XX..
CarRotation8;DOWN (ACTUAL)
;.byte %00000000
.byte %00011000; ...XX...
.byte %01011010; .X.XX.X.
.byte %01111110; .XXXXXX.
.byte %01011010; .X.XX.X.
.byte %00011000; ...XX...
.byte %01100110; .XX..XX.
.byte %01111110; .XXXXXX.
.byte %01011010; .X.XX.X.
;missiles are used as pseudoplayers
;data is encoded as width and pixel offsets.
;76543210
;XXXX <- OFFSET (typically 0 through +8 pixels)
; XX <- NUSIZ data
;EXAMPLE:
;LDA (M0_ShapeFrame),Y ;
;STA HMM0 ;
;LSL ;
;LSL ;
;STA NUSIZ0 ;
;32 bytes used
Ped1_1; OOOOWW__
.byte %11110100 ; .XX.....
.byte %11100000 ; ..X.....
.byte %11011000 ; ...XXXX.
.byte %11010100 ; ...XX...
.byte %11111000 ; .XXXX...
.byte %00000000 ; ........
.byte %11010100 ; ...XX...
.byte %11010100 ; ...XX...
Ped1_2; OOOOWW__
.byte %11010100 ; ...XX...
.byte %11010100 ; ...XX...
.byte %11010100 ; ...XX...
.byte %11010100 ; ...XX...
.byte %11010100 ; ...XX...
.byte %00000000 ; ........
.byte %11010100 ; ...XX...
.byte %11010100 ; ...XX...
Ped1_3; OOOOWW__
.byte %11110100 ; .XX.....
.byte %00000000 ; ..X.....
.byte %11011100 ; ...XXXX.
.byte %11100100 ; ..XX....
.byte %11010100 ; ...XX...
.byte %00000000 ; ........
.byte %11010100 ; ...XX...
.byte %11010100 ; ...XX...
Ped1_4; OOOOWW__
.byte %11011100 ; ...XXXX.
.byte %11010000 ; ...X....
.byte %11011100 ; ...XXXX.
.byte %11010100 ; ...XX...
.byte %00001100 ; XXXX....
.byte %11101100 ; ..XXXX..
.byte %11110100 ; .XX.....
.byte %11110100 ; .XX.....
;add score graphics later
org $FFFC
.word Start
.word Start
Attachment:
DD_0016.bin
Description: Binary data
| Current Thread |
|---|
|
| <- Previous | Index | Next -> |
|---|---|---|
| [stella] programming on PDAs, Glenn Saunders | Thread | Re: [stella] Unending VDEL hell, Eckhard Stolberg |
| [stella] programming on PDAs, Glenn Saunders | Date | Re: [stella] Cosmic Ark disassemble, Gary Szwiec |
| Month |