Subject: [stella] SCSIcide 1.09: Paddle, flicker, and optimization From: Joe Grand <jgrand@xxxxxxxxxxxxxx> Date: Mon, 02 Jul 2001 00:12:51 -0400 |
; ; Project name: SCSIcide v1.09 ; Game concept for the Atari 2600 VCS ; ; Copyright 2001 ; By Joe Grand, jgrand@xxxxxxxxxxxxxx (http://www.mindspring.com/~jgrand/atari) ; Last update: 1.Jul.2001 ; High score: $12329A ; ; dasm source.s -f3 -osource.bin to compile ; ; Tested with StellaX v1.1.3a and Atari 2600jr w/ Supercharger ; ; NEW ADDITIONS ; ; o Paddle control for drivehead ; o Button starts each level ; o Don't draw drivehead if game hasn't started or is over ; o "Select" switch functionality enabled (for multiple game variations) ; o Changed the scoring to make more sense ; o Points for each read bit = Level number * Latency buffer remaining ; o Score decreases by 1 if required data bit is missed ; o Score decreases by 1 if incorrect data bit is read ; o The 1st byte of the score is now the level (platter) number ; ; ; TO DO ; ; o Fixed all known timing/flicker issues ; o Display title screen (with screensaver) ; o Add sound ; o Easter egg :) ; ; ; [Select - Multiple Game Variations] ; ; o Bit size ; o Bad sectors (cannot touch the drivehead) ; ; [Difficulty Switch] ; ; o Smooth v. track-to-track movement ; o Normal v. oversized drivehead ; o NTSC v. PAL ; processor 6502 include vcs.h SEG.U defines NUMGRP = 10 ; Number of graphics (player 1 data) GRPHEIGHT = 7 ; Height of each graphic XMIN = 8 XMAX = 158 HORPOS_P0 = 148 ; Horizontal position player 0 (drivehead) - fixed COLOR_SCORE = $B8 ; Score/Time Remaining color (Green) COLOR_GAUGE = $34 ; Gas gauge background color (Red) COLOR_LINE = $F4 ; Line color (Light Brown) COLOR_TRACK = $F2 ; Track color (Brown) COLOR_BG = $00 ; Background color (Black) SEG.U vars org $80 ; Allocate memory, PIA has 128 bytes of RAM ($80-$FF). Stack from $FF temp ds 1 temp_stack ds 1 loopCount ds 1 ; Counter for loops pot0 ds 1 ; Player 0's paddle value startDelay ds 1 ; Timer for paddle switch debounce selectDelay ds 1 ; Timer for select autorepeat horPosP1 ds NUMGRP ; Horizontal position player 1 (data) horPosP1_FC ds NUMGRP horMotP1 ds NUMGRP ; Motion values player 1 (data) verPosP0 ds 1 ; Vertical position player 0 (drivehead) grpCount ds 1 ; Group counter grpY ds NUMGRP grpY_Next ds 1 ; First line of next group grpDistance ds 1 ; Distance between player0 and top of group nodata ds 1 nocc ds 1 coll ds NUMGRP ; Collision flags dataColorTable ds NUMGRP ; Color order of data for current level currentDataColor ds 1 ; Color of data to match dataColorIndex ds 1 ; Index to the next data color in table color ds 2 ; Color flags (GetNextColor) color2 ds 2 ; Color flags (RandomizeColorTable) score ds 3 ; Player score (6 hex digits: 00 00 00) ; / | \ ; score +1 +2 ; Platter Level Actual Score scorePtr0 ds 2 ; Pointer to score shapes scorePtr1 ds 2 scorePtr2 ds 2 scorePtr3 ds 2 scorePtr4 ds 2 scorePtr5 ds 2 gauge_PF ds 2 ; Data latency buffer, PF0 and PF1 (1st half of screen) bitCount ds 1 ; Number of data bits read bitCount_PF ds 3 ; PF0, PF1 and PF2 (2nd half of screen) gameNumber ds 1 ; Current game variation being played (0 = game over, 1-8) gameHasBeenPlayed ds 1 levelDone ds 1 ; Flag set when level is completed rand1 ds 1 ; Variables for random bit/byte generation routine rand2 ds 1 rand3 ds 1 rand4 ds 1 SEG code org $F800 ; Limit ourselves to 2K like the old days ;org $F000 ; 4K to burn 2732 ROM Start ; ; The 2600 powers up in a completely random state, except for the PC which ; is set to the location at $FFC. Therefore the first thing we must do is ; to set everything up inside the 6502. ; SEI ; Disable interrupts, if there are any. CLD ; Clear BCD math bit. LDX #$FF TXS ; Set stack to beginning. ; Loop to clear memory and TIA registers LDA #0 B1 STA 0,X DEX BNE B1 ; The above routine does not clear location 0, which is VSYNC JSR GameInit ; Initial variable and register setup MainLoop JSR VerticalBlank ; Execute the vertical blank. JSR CheckSwitches ; Check console switches. JSR GameCalc ; Do calculations during VBLANK JSR DrawScreen ; Draw the screen JSR OverScan ; Do more calculations during overscan JMP MainLoop ; Continue forever. VerticalBlank ;*********************** VERTICAL BLANK HANDLER ; ; Beginning of the frame - at the end of overscan. ; LDA #$82 ; VB_DumpPots & VB_Enable (Thanks Eckhard!) STA VBLANK ; Discharge paddle potentiometer LDA #2 ; VBLANK was set at the beginning of overscan. STA WSYNC STA WSYNC STA WSYNC STA VSYNC ; Begin vertical sync STA WSYNC ; First line of VSYNC STA WSYNC ; Second line of VSYNC ; Set the timer to go off just before the end of vertical blank space ; 37 scanlines * 76 cycles = 2812 cycles / 64 = approx. 44 LDA #44 STA TIM64T ; ; End the VSYNC period. ; LDA #0 STA WSYNC ; Third line of VSYNC. STA VSYNC ; (0) LDA #$2 STA VBLANK ; Start recharge of paddle capacitor RTS CheckSwitches ;*************************** CONSOLE SWITCH HANDLER LDA SWCHB ; Read the switches LSR ; Shift the Reset switch ROR ; Rotate Reset to Negative flag and Carry has select BMI NoReset Go ; ; Start game if reset ; LDA gameNumber ; If this is a new game, but game has already been selected BNE Play CLC LDA score+2 ; Game number = 1-8 (0 = game over) ADC #1 Play STA gameNumber JSR DataInit JSR BonusDone ; Fill latency buffer LDA #1 STA levelDone STA gameHasBeenPlayed RTS NoReset BCS NotSelTime ; Was select pressed? LDA gameHasBeenPlayed ; If a game is in action or has been played once, BNE NotSelTime ; disable Select so it doesn't affect game or overwrite previous score LDA selectDelay BNE SaveSelDelay CLC LDA score+2 ; Game number is stored in score while it is being selected ADC #1 ; Increment the game selected AND #7 ; Make sure the game number is 0-7 STA score+2 LDA #15 ; Delay STA selectDelay JMP NotSelTime SaveSelDelay DEC selectDelay NotSelTime ; ; Examine Difficulty Switch settings ; RTS GameCalc ;******************************* GAME CALCULATION ROUTINES LDA #1 STA pot0 ; ; Start new level when paddle button is pressed ; LDA startDelay BNE Delay2 LDA levelDone ; If flag is set... BEQ NotReady LDA #15 ; Delay... STA startDelay Delay2 DEC startDelay BNE NotReady LDA SWCHA ; Then check for button press... BMI NotReady JSR NextLevel ; ...to begin next level NotReady ; ; Check to see if latency buffer is empty. If it is, end game ; LDA gauge_PF BNE NotEmpty JSR EndGame NotEmpty ; ; Move data objects horizontally (Courtesy of Piero Cavina PCMSD 1.1 source) ; LDX #NUMGRP-1 MoveLP LDA horPosP1,X ; Get current position CLC ADC horMotP1,X ; Increment/decrement by motion value STA horPosP1,X CMP #XMIN ; Are we at the minimum X value (left edge of screen)? BCC SwapX0 CMP #XMAX ; Are we at the maximum X value (right edge of screen)? BCS SwapX JMP MoveDone ; We must be somewhere in between SwapX0 LDA #XMIN ; Minimum SEC SBC horPosP1,X CLC ADC #XMIN STA horPosP1,X SwapX ; Maximum LDA #XMIN ; Wrap around to the beginning of the track STA horPosP1,X ; Is this the current data bit? If so, decrement latency buffer LDA currentDataColor CMP dataColorTable,X BNE MoveDone LDA levelDone ; If level is not done, game is in progress... BNE MoveDone JSR DecGauge ; ...so gauge can be decremented JSR DecScore MoveDone LDA horPosP1,X ; Convert X position to FC format JSR Convert STA horPosP1_FC,X DEX BPL MoveLP LDA #0 STA grpCount ; Initialize group counter STA grpY ; First line of first group LDA #GRPHEIGHT+1 STA grpY_Next ; First line of next (second) group LDA verPosP0 STA grpDistance ; ; Set pointers to number data (based on current score) ; score score+1 score+2 ; LDX #3-1 LDY #10 ScoreLoop LDA score,X AND #$0F ; Mask it ASL ; Multiply by 8 ASL ASL CLC ADC #<FontPage ; Store the 2-byte pointer STA scorePtr0,Y LDA #0 ADC #>FontPage STA scorePtr0+1,Y DEY DEY LDA score,X AND #$F0 ; Mask it LSR ; $00,$08,$10,$18,$20, ... ( / 8 = value) ADC #<FontPage ; Store the 2-byte pointer STA scorePtr0,Y LDA #0 ADC #>FontPage STA scorePtr0+1,Y DEY DEY DEX BPL ScoreLoop RTS DrawScreen ;**************************** SCREEN DRAWING ROUTINES ; ; Initialize display variables. ; LDA #COLOR_BG STA COLUBK ; Background will be black LDA currentDataColor ; Set the score color (P0 and P1) STA COLUP0 STA COLUP1 LDX #3 STX NUSIZ0 ; Three copies of player, close together (for score) STX NUSIZ1 WaitVBlank LDA INTIM ; Loop until timer is done - wait for the proper scanline ; (i.e. somewhere in the last line of VBLANK) BNE WaitVBlank ; Whew! We're at the beginning of the frame LDA #0 STA WSYNC ; End the current scanline STA HMOVE ; Add horizontal motion to position sprites STA VBLANK ; End the VBLANK period with a zero, enable video, charge pot. STA WSYNC ; Wait 2 scanlines before drawing score STA WSYNC ; ; Horizontally position P0 and P1 for score ; LDX #22 Pause1 DEX BNE Pause1 STA RESP0 STA WSYNC LDX #22 Pause2 DEX BNE Pause2 NOP STA RESP1 STA HMCLR LDA #%10100000 ; P1 position 2 less than P0 STA HMP1 LDA #%11000000 STA HMP0 STA WSYNC STA HMOVE STA WSYNC ScanLoop ; ================================== SCANNING LOOP ; ; There are 228/3 cycles per line, so we have a maximum of 73 cycles ; after STA WSYNC ; ; Display the scores - 6 digit, courtesy of Robin Harbron ; LDA #8-1 ; Lines to display STA loopCount LDX #9 Pause3 DEX BNE Pause3 NOP NOP NOP TSX STX temp_stack ; Save the stack pointer (Andrew Davie) DrawScore LDY loopCount ; 3 LDA (scorePtr0),Y ; 5 STA GRP0 ; 3 = 11 BIT $00 LDA (scorePtr1),Y ; 5 STA GRP1 ; 3 LDA (scorePtr5),Y ; 5 TAX ; 2 TXS ; 2 LDA (scorePtr2),Y ; 5 STA temp ; 3 LDA (scorePtr3),Y ; 5 TAX ; 2 LDA (scorePtr4),Y ; 5 = 37 LDY temp ; 3 STY GRP0 ; 3 STX GRP1 ; 3 STA GRP0 ; 3 TSX ; 2 STX GRP1 ; 3 = 17 DEC loopCount ; 5 BPL DrawScore ; 3 = 8 LDX temp_stack TXS LDA #0 STA GRP0 STA GRP1 ; ; Skip down a few lines ; LDY #4 DrawWait STA WSYNC DEY BNE DrawWait ; ; Position drivehead (horizontally) ; LDA #HORPOS_P0 ; Convert Player0 X position to FC format JSR Convert STA WSYNC ; Prepare to position Player0 STA HMP0 ; Remember, we're still doing VBLANK now AND #$0F TAY PosWait DEY BPL PosWait STA RESP0 STA WSYNC STA HMOVE LDX #P_Single STX NUSIZ0 ; One copy of player STX NUSIZ1 LDA currentDataColor STA COLUP0 STA HMCLR ; Clear horizontal motion (of Player 0) LDA #0 ; Use playfield (black) to shorten length of track STA COLUPF STA PF1 STA PF2 LDA #$30 STA PF0 LDA #$05 ; Reflect,No score,High Priority,1 pixel-wide ball STA CTRLPF ; ; Start drawing the actual disk playfield (10 lanes) ; ; We're going to draw #NUMGRP groups, each made of: ; 2 scanlines for Player1 positioning with Player0, plus ; #GRPHEIGHT*2 scanlines with Player1 and Player0. ; ; (Courtesy of Piero Cavina PCMSD 1.1 source) ; Kernel LDA grpDistance ; Distance between Player0 <-> top of group CMP #GRPHEIGHT+1 ; Is Player0 inside current group? BCC DrawP0 ; Yes, we'll draw it... LDX #0 ; No, draw instead a blank sprite BEQ BlankP0 DrawP0 LDA grpY_Next ; We must draw Player0, and we'll start SEC ; from the (grpY_Next-verPosP0)th byte. SBC verPosP0 TAX ; Put the index to the first byte into X BlankP0 STX temp ; and remember it. LDY grpCount ; Store any collision between Player0 and LDA CXPPMM ; Player1 happened while drawing the last group. STA coll,Y LDA dataColorTable,Y STA COLUP1 LDA horPosP1_FC,Y ; Get Player1 position LDY gameNumber ; If game over, don't draw drivehead BEQ NoHead LDY HeadFrame,X ; Get Player0 pattern NoHead STA WSYNC ; Start with a new scanline. STY GRP0 ; Set Player0 pattern STA HMP1 ; Prepare Player1 fine motion AND #$0F ; Prepare Player1 coarse positioning TAY PosWait2 DEY ; Waste time BPL PosWait2 STA RESP1 ; Position Player1 STA WSYNC ; Wait for next scanline STA HMOVE ; Apply fine motion LDA #COLOR_LINE STA COLUBK ; Draw track seperator ; ; Now prepare various things for the next group ; LDA grpY_Next ; Update this group and next group STA grpY ; top line numbers CLC ADC #GRPHEIGHT+1 STA grpY_Next LDA verPosP0 ; Find out which 'slice' SEC ; of Player0 we'll have to draw. SBC grpY ; We need the distance of Player0 BPL DPos ; from the top of the group. EOR #$FF CLC ADC #1 ; A = ABS(verPosP0-grpY) DPos STA grpDistance LDX temp ; Pointer to the next byte of Player0 INX ; pattern. Use X while drawing the group LDA #0 ; Clear collisions STA CXCLR LDY #GRPHEIGHT-1 ; Initialize line counter (going backwards) DrawGrp LDA #0 STA WSYNC ; Wait for a new line LDA #COLOR_TRACK STA COLUBK ; Set background color LDA DataFrame,Y STA GRP1 ; Set Player1 shape LDA gameNumber ; If game over, don't draw drivehead BEQ NoHead2 LDA HeadFrame,X NoHead2 STA GRP0 ; Set Player0 shape LDA INPT0 ; Read paddle 0 BMI Charged ; Capacitor already charged, skip increment INC pot0 ; Increment paddle position value Charged STA WSYNC ; Wait for a new scanline INX ; Update the index to next byte of Player0 DEY ; Decrement line counter BPL DrawGrp ; Go on with this group if needed INC grpCount ; Increment current group number LDA grpCount ; CMP #NUMGRP ; Is there another group to do? BCS OuterKernel ; No, exit JMP Kernel ; Yes, go back. (Using JMP because a branch ; would be out of range) OuterKernel STA WSYNC ; Finish current scanline LDA #0 ; Avoid bleeding STA GRP0 STA GRP1 LDA #COLOR_LINE ; Draw bottom track seperator STA COLUBK STA WSYNC LDA #COLOR_BG ; Black line STA COLUBK LDY #8 DrawWait2 STA WSYNC DEY BNE DrawWait2 ; ; Draw data latency buffer and bit counter ; LDA #$30 STA CTRLPF ; No Reflect,No score,Low Priority,8 pixel-wide ball LDX #$07 ; Number of lines alike NxtLine STA WSYNC ; Wait for line to finish LDA #COLOR_SCORE ; [0] +4 green STA COLUPF ; [4] +3 LDA #COLOR_GAUGE ; [7] +4 red STA COLUBK ; [11] +3 set background ; First half of screen LDA gauge_PF ; [14] +3 STA PF0 ; [17] +3 LDA gauge_PF+1 ; [20] +3 STA PF1 ; [23] +3 LDA #0 ; [26] +3 STA PF2 ; [29] +3 STA PF2 ; [32] +3 Used in place of NOP for extra cycle NOP ; [35] +2 LDY currentDataColor ; [37] +4 STA COLUBK ; [41] +3 end of gauge -> background color back to black ; Second half of screen - display number of bytes currently retrieved STY COLUPF ; [44] +3 LDA bitCount_PF ; [47] +4 STA PF0 ; [51] +3 LDA bitCount_PF+1 ; [54] +4 STA PF1 ; [58] +3 LDA bitCount_PF+2 ; [61] +4 STA PF2 ; [65] +3 DEX ; [68] +5 BNE NxtLine ; [73] +3 (take branch) ; ; Clear all registers here to prevent any possible bleeding. ; LDA #2 STA WSYNC ; Finish this scanline. STA VBLANK ; Make TIA output invisible, ; Now we need to worry about it bleeding when we turn ; the TIA output back on. LDY #0 STY PF0 STY PF1 STY PF2 RTS OverScan ;***************************** OVERSCAN CALCULATIONS (2280 cycles) ; Set the timer to go off just before the end of overscan ; 30 scanlines * 76 cycles = 2280 cycles / 64 = approx. 35 LDA #35 STA TIM64T ; If game is over, disable paddle LDA gameNumber BNE GameInPlay JMP NoStick GameInPlay ; ; Set new vertical position of drivehead based on paddle value ; LDX pot0 STX verPosP0 NoStick ; ; Check and handle any collisions between P1 (data) and P0 (drivehead) ; LDA gameNumber ; Don't read button if game is over BEQ NoButton LDA levelDone ; If level is completed and we're waiting for a new one to start BNE NoButton LDA nodata BNE Delay LDA SWCHA ; Has fire button been pressed? BMI NoButton ; If yes, check for collisions LDX #NUMGRP-1 LDA #0 LoopColl ; Check all collision flags ORA coll,X DEX BPL LoopColl CMP #0 ; If there are no collisions... BMI DataExists JSR DecGauge ; There is NO data to read, so decrement latency buffer LDA #20 ; Delay to prevent multiple collisions STA nodata JMP NoButton Delay DEC nodata DataExists LDX #NUMGRP-1 CheckCollisions LDA nocc BNE CollisionDelay LDA coll,X BPL NoCollision ; Button has been pressed and there is data to read STX temp DEX BPL NoRoll ; We are looking at the previous groups collision LDX #NUMGRP-1 ; So if X=0, need to set to X=9 NoRoll ; Is the color correct? LDA currentDataColor CMP dataColorTable,X BEQ SameColor ; If not, decrement score JSR DecScore JMP NoButton SameColor LDA #0 ; Hide/remove block STA horPosP1,X STA horMotP1,X JSR IncCount ; Increase bit counter JSR GetNextColor ; Change to next color JSR IncBonus ; Refilll latency buffer and give bonus points LDA #20 ; Delay to prevent multiple collisions STA nocc LDX temp CollisionDelay DEC nocc NoCollision LDA #0 ; Clear collision flag STA coll,X DEX BPL CheckCollisions NoButton WaitOverscan LDA INTIM ; Loop until timer is done - wait for the proper scanline BNE WaitOverscan RTS GameInit ;***************************** INITIAL VARIABLE & REGISTER SETUP ; ; Called at initial power on ; LDA #$6D ; Need to be initialized to any non-zero value STA rand1 STA rand2 STA rand3 STA rand4 JSR DataInit ; We need to set up some of the data before the game starts ; ; Clear data pointers ; LDX #12-1 LDA #0 Clear2 STA scorePtr0,X DEX BPL Clear2 STA WSYNC LDY #3 Pos0 DEY BNE Pos0 STA RESP0 ; A = 0 STA gameNumber STA gameHasBeenPlayed LDA #COLOR_SCORE ; Color of score and drivehead before the game starts STA currentDataColor RTS DataInit ; ; Called when Reset switch is pressed ; LDA #0 STA nodata STA nocc STA dataColorIndex STA startDelay STA selectDelay ; Color flags STA color STA color+1 STA color2 STA color2+1 ; Score STA score STA score+1 STA score+2 ; Clear bit counter STA bitCount STA bitCount_PF STA bitCount_PF+1 STA bitCount_PF+2 ; Clear latency buffer STA gauge_PF STA gauge_PF+1 LDX #NUMGRP-1 NoMotion2 STA horPosP1,X STA horMotP1,X DEX BPL NoMotion2 ; Player 0 (drivehead) LDA #36 ; Start positioned in center STA verPosP0 JSR RandomizeColorTable ; Set color order of data bits to begin JSR GetNextColor ; Set color of each data block RTS ; ; Set the next color of data block to retrieve ; GetNextColor ; ; If all data bits have been read, go to next level ; LDA bitCount CMP #NUMGRP BNE MoreData JSR LevelDone MoreData ; Use random number to select next color (to prevent patterns) JSR RandomNibble ; Random number returned in A ; Mod 10 AND #$0F CMP #10 BPL Mod JMP NoMod Mod CLC SBC #9 NoMod STA temp ; If random number < 8, use color+1, else use color ; xxxx xx00 0000 0000 ; Bit set = color has been used CMP #8 BPL Msb TAX LDA #0 SEC ; Set Carry Shift ROL DEX BPL Shift STA temp_stack AND color+1 BNE MoreData ; If color has already been done, get a new value LDA temp_stack ORA color+1 ; Set flag STA color+1 JMP ColorDone Msb CLC SBC #7 TAX LDA #0 SEC ; Set Carry Shift2 ROL DEX BPL Shift2 STA temp_stack AND color BNE MoreData ; If color has already been done, get a new value LDA temp_stack ORA color ; Set flag STA color ColorDone LDX temp LDA dataColorTable,X STA currentDataColor RTS ; ; Randomly arrange the color order of data bits ; RandomizeColorTable LDY #NUMGRP-1 Table JSR RandomNibble ; Random number returned in A ; Mod 10 AND #$0F CMP #10 BPL Mod2 JMP NoMod2 Mod2 CLC SBC #9 NoMod2 STA temp ; If random number < 8, use color2+1, else use color2 ; xxxx xx00 0000 0000 ; Bit set = color has been used CMP #8 BPL Msb2 TAX LDA #0 SEC ; Set Carry Shift3 ROL DEX BPL Shift3 STA temp_stack AND color2+1 BNE Table ; If color has already been done, get a new value LDA temp_stack ORA color2+1 ; Set flag STA color2+1 JMP ColorTableDone Msb2 CLC SBC #7 TAX LDA #0 SEC ; Set Carry Shift4 ROL DEX BPL Shift4 STA temp_stack AND color2 BNE Table ; If color has already been done, get a new value LDA temp_stack ORA color2 ; Set flag STA color2 ColorTableDone LDX temp LDA DataColors,X STA dataColorTable,Y DEY BPL Table RTS ; ; Give extra points: Platter level number (score) * remaining latency buffer ; IncBonus LDX gauge_PF BEQ BonusDone JSR DecGauge LDA score JSR IncScore JMP IncBonus BonusDone ; Refill latency buffer LDA #$F0 STA gauge_PF LDA #$FF STA gauge_PF+1 RTS ; ; Level is complete, clear variables and set flag ; LevelDone ; Clear bit counter LDA #0 STA bitCount STA bitCount_PF STA bitCount_PF+1 STA bitCount_PF+2 ; Clear color flags STA color STA color+1 STA color2 STA color2+1 JSR RandomizeColorTable ; ; Play tune? ; LDA #1 STA levelDone RTS ; ; Go to next level ; NextLevel LDA #0 STA levelDone ; ; Set objects position and motion ; LDY #NUMGRP-1 NewMotion JSR RandomByte ; Random number returned in A AND #$7F ; Choose random positioning of data bits STA horPosP1,Y CLC LDA score ; Increase speed every other level ADC #2 LSR ; /2 STA horMotP1,Y DEY BPL NewMotion INC score ; Increment level number RTS ; ; End the game ; Stop all data bits, prevent drive head from moving ; Play tune? ; EndGame LDA #0 STA gameNumber LDX #NUMGRP-1 NoMotion STA horMotP1,X DEX BPL NoMotion RTS ; ; Increase the score by A (up to $FF) ; Handles roll of score from 00FF to 0100, etc. ; IncScore CLC ; Clear carry LDX #2-1 Loop ADC score+1,X ; Add LSB STA score+1,X LDA #0 ; MSB 2 bytes = 0 DEX BPL Loop RTS ; ; Decrement the score by 1 point ; Handle roll of score from 0100 to 00FF, etc. ; Prevent roll if score is already at 0000 ; DecScore ; Check for 0000 LDA score+2 BNE Decrement ; If not 0, just decrement LSB ORA score+1 BEQ DecDone ; If score has rolled, decrement MSB, too DEC score+1 Decrement DEC score+2 DecDone RTS ; ; Increase/decrease the value of the data latency buffer by 1 pixel ; IncGauge LDA gauge_PF CMP #$F0 BEQ IncPF ASL ORA #$10 STA gauge_PF JMP IncGaugeDone IncPF LDA gauge_PF+1 LSR ORA #$80 STA gauge_PF+1 IncGaugeDone RTS DecGauge LDA gauge_PF+1 CMP #$0 BEQ DecPF0 ASL STA gauge_PF+1 JMP DecGaugeDone DecPF0 LDA gauge_PF LSR AND #$F0 STA gauge_PF DecGaugeDone RTS ; ; Increase the value of the bit counter by 2 pixels, increment counter variable ; IncCount INC bitCount LDA bitCount_PF CMP #$F0 BEQ IncPF1 ASL ASL ORA #$30 STA bitCount_PF JMP IncDone IncPF1 LDA bitCount_PF+1 CMP #$FF BEQ IncPF2 LSR LSR ORA #$C0 STA bitCount_PF+1 JMP IncDone IncPF2 LDA bitCount_PF+2 ASL ASL ORA #$03 STA bitCount_PF+2 IncDone RTS ; ; Random number generation (courtesy of Erik Mooney, March 1997) ; http://www.biglist.com/lists/stella/archives/199703/msg00296.html ; ; rand1, rand2, rand3, rand4 are RAM locations, initialized to any non-zero ; value at program start ; ; RandomBit generates one random bit. ; RandomByte generates one random byte and returns it in the accumulator. ; RandomNibble generates one random nibble (in LSB) and returns it in the accumulator. ; RandomBit LDA rand4 ASL ASL ASL EOR rand4 ; New bit is now in bit 6 of A ASL ASL ; New bit is now in carry ROL rand1 ; Shift new bit into bit 0 of register, bit 7 goes into carry ROL rand2 ; Shift old bit 7 into bit 8, etc. ROL rand3 ROL rand4 RTS RandomByte LDX #8 JMP RandomByte1 RandomNibble LDX #4 RandomByte1 JSR RandomBit DEX BNE RandomByte1 LDA rand1 RTS ; ; Straight from "Air-Sea Battle", here's the routine ; to convert from standard X positions to FC positions ; Convert STA temp BPL LF34B CMP #$9E BCC LF34B LDA #$00 STA temp LF34B LSR LSR LSR LSR TAY LDA temp AND #$0F STY temp CLC ADC temp CMP #$0F BCC LF360 SBC #$0F INY LF360 CMP #$08 EOR #$0F BCS LF369 ADC #$01 DEY LF369 INY ASL ASL ASL ASL STA temp TYA ORA temp RTS DataColors ; Need 10 distinct colors to avoid confusion .byte $04, $16, $2E, $34, $44, $6C, $74, $B8, $D4, $1C HeadFrame ; Note the leading and trailing $00's .byte $00, $00, $00, $00, $00, $00, $00, $00, $00 ; 9 .byte %00011110 ; | XXXX | .byte %00111011 ; | XXX XX| .byte %00110000 ; | XX | .byte %11111000 ; |XXXXX | .byte %00110000 ; | XX | .byte %00111011 ; | XXX XX| .byte %00011110 ; | XXXX | .byte $00, $00, $00, $00, $00, $00, $00 ; 7 DataFrame .byte %00000000 ; | | .byte %11111111 ; |XXXXXXXX| .byte %11111111 ; |XXXXXXXX| .byte %11111111 ; |XXXXXXXX| .byte %11111111 ; |XXXXXXXX| .byte %11111111 ; |XXXXXXXX| .byte %00000000 ; | | ; All shapes are upside down to allow decrementing by Y as both ; a counter and a shape index ; org $FE00 ; *********************** GRAPHICS DATA ; ; Numeric font ; FontPage Zero ; .byte %01111100 ; | XXXXX | ; .byte %01100100 ; | XX X | ; .byte %01100100 ; | XX X | ; .byte %01100100 ; | XX X | ; .byte %01100100 ; | XX X | ; .byte %01100100 ; | XX X | ; .byte %01100100 ; | XX X | ; .byte %01111100 ; | XXXXX | .byte %00111100 ; | XXXX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %00111100 ; | XXXX | One ; .byte %00011000 ; | XX | ; .byte %00011000 ; | XX | ; .byte %00011000 ; | XX | ; .byte %00011000 ; | XX | ; .byte %00010000 ; | X | ; .byte %00010000 ; | X | ; .byte %00010000 ; | X | ; .byte %00010000 ; | X | .byte %00111100 ; | XXXX | .byte %00011000 ; | XX | .byte %00011000 ; | XX | .byte %00011000 ; | XX | .byte %00011000 ; | XX | .byte %00011000 ; | XX | .byte %00111000 ; | XXX | .byte %00011000 ; | XX | Two .byte %01111110 ; | XXXXXX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %00111100 ; | XXXX | .byte %00000110 ; | XX | .byte %00000110 ; | XX | .byte %01000110 ; | X XX | .byte %00111100 ; | XXXX | Three .byte %00111100 ; | XXXX | .byte %01000110 ; | X XX | .byte %00000110 ; | XX | .byte %00001100 ; | XX | .byte %00001100 ; | XX | .byte %00000110 ; | XX | .byte %01000110 ; | X XX | .byte %00111100 ; | XXXX | Four .byte %00001100 ; | XX | .byte %00001100 ; | XX | .byte %00001100 ; | XX | .byte %01111110 ; | XXXXXX | .byte %01001100 ; | X XX | .byte %00101100 ; | X XX | .byte %00011100 ; | XXX | .byte %00001100 ; | XX | Five .byte %01111100 ; | XXXXX | .byte %01000110 ; | X XX | .byte %00000110 ; | XX | .byte %00000110 ; | XX | .byte %01111100 ; | XXXXX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01111110 ; | XXXXXX | Six .byte %00111100 ; | XXXX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01111100 ; | XXXXX | .byte %01100000 ; | XX | .byte %01100010 ; | XX X | .byte %00111100 ; | XXXX | Seven .byte %00011000 ; | XX | .byte %00011000 ; | XX | .byte %00011000 ; | XX | .byte %00011000 ; | XX | .byte %00001100 ; | XX | .byte %00000110 ; | XX | .byte %01000010 ; | X X | .byte %01111110 ; | XXXXXX | Eight .byte %00111100 ; | XXXX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %00111100 ; | XXXX | .byte %00111100 ; | XXXX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %00111100 ; | XXXX | Nine .byte %00111100 ; | XXXX | .byte %01000110 ; | X XX | .byte %00000110 ; | XX | .byte %00111110 ; | XXXXX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %00111100 ; | XXXX | A .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01111110 ; | XXXXXX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %00111100 ; | XXXX | B .byte %01111100 ; | XXXXX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01111100 ; | XXXXX | .byte %01111100 ; | XXXXX | .byte %01100110 ; | XX XX | .byte %01100110 ; | XX XX | .byte %01111100 ; | XXXXX | C .byte %00111100 ; | XXXX | .byte %01100110 ; | XX XX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01100110 ; | XX XX | .byte %00111100 ; | XXXX | D .byte %01111100 ; | XXXXX | .byte %01100110 ; | XX XX | .byte %01100010 ; | XX X | .byte %01100010 ; | XX X | .byte %01100010 ; | XX X | .byte %01100010 ; | XX X | .byte %01100110 ; | XX XX | .byte %01111100 ; | XXXXX | E .byte %01111110 ; | XXXXXX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01111110 ; | XXXXXX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01111110 ; | XXXXXX | F .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01111110 ; | XXXXXX | .byte %01100000 ; | XX | .byte %01100000 ; | XX | .byte %01111110 ; | XXXXXX | .byte "SCSIcide" .byte "J. Grand" .byte "2001" ; ; Avoid $FFF8 to allow use with Supercharger ; ; ; Set up the 6502 interrupt vector table ; org $FFFC .word Start ; Reset .word Start ; IRQ END
Attachment:
scsi109.bin
Description: Binary data
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [stella] Home Vision repro cart, Russ Perry Jr | Thread | Re: [stella] 2600 emu for GBA, Glenn Saunders |
Re: [stella] Home Vision repro cart, Russ Perry Jr | Date | Re: [stella] 2600 emu for GBA, Glenn Saunders |
Month |