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 |