ORG $F000 *-----------------------------------------------------------------------* * This disassembly of the Vectrex ROM was done by Bruce Tomlin * * (btomlin@aol.com), and is based in part on a disassembly done by * * Fred Taft (fred@hp-pcd.cv.hp.com). * *-----------------------------------------------------------------------* INCLUDE VECTREX.INC *-----------------------------------------------------------------------* * F000 Start * * * * Jump here to restart the Vectrex and re-initialize the OS. If the * * cold start flag is correct (it should be unless you just turned the * * Vectrex on), the cold start code is skipped. * * * * On cold start, the high score is cleared, and the power-on screen * * is displayed with the power-on music. * *-----------------------------------------------------------------------* F000=10CECBEA Start: LDS #Vec_Default_Stk Set up stack pointer F004 BDF18B JSR Init_OS Initialize system F007 CC7321 LDD #$7321 Check cold start flag F00A 10B3CBFE CMPD Vec_Cold_Flag F00E 275C BEQ Warm_Start Branch if warm start F010 FDCBFE STD Vec_Cold_Flag Initialize cold start flag F013 7CC83B INC $C83B Set high score invalid flag F016 8ECBEB LDX #Vec_High_Score Clear high score F019 BDF84F JSR Clear_Score * First power-up loop. This prints the "VECTREX" * power-on screen and plays the power-on music. F01C=BDF1AF LF01C JSR DP_to_C8 DP to RAM F01F DC25 LDD PB7 enabled F15B 970B STA 0 if joystick is right or up of center. * * * * Joy_Analog: * * A successive approximation algorithm is used to read * * the actual value of the joystick pot, a signed value. * * In this case, $C81A must be set to a power of 2, to * * to control conversion resolution; 0x80 is least * * accurate, and 0x00is most accurate. * * * * ENTRY DP = $D0 * * * * D-reg, X-reg trashed * *-----------------------------------------------------------------------* F1F5=7AC823 Joy_Analog: DEC $C823 Set analog mode flag F1F8 8EC81F Joy_Digital: LDX #Vec_Joy_Mux_1_X Point to first pot F1FB=A680 LF1FB LDA ,X+ Read it if enabled F1FD 260C BNE LF20B F1FF=8CC823 LF1FF CMPX #$C823 Go back untl all pots read F202 26F7 BNE LF1FB F204 6F84 CLR ,X X points to $C823, clear it F206 8601 LDA #$01 F208 9700 STA = 0, then the music data will be * * copied; however, as soon as a register number < 0 is encountered, * * the copy will stop. * * * * ENTRY DP = $D0 * * U-reg = pointer to the block of sound data * * * * D-reg, X-reg, U-reg trashed * *-----------------------------------------------------------------------* F27D=8EC800 Sound_Bytes: LDX #Vec_Snd_Shadow Point to shadow memory F280 2002 BRA Sound_Bytes_x F282=8DD5 LF282 BSR Sound_Byte_x Update the sound register F284=ECC1 Sound_Bytes_x: LDD ,U++ Get next next pair of bytes F286 2AFA BPL LF282 Go back if not end of list F288 39 RTS *-----------------------------------------------------------------------* * F289 Do_Sound * * F28C Do_Sound_x? (apparently never used) * * * * This routine will start/continue making the sound which was first * * set up by your call to Init_Music. This routine should normally * * be called right after your call to Wait_Recal. It takes the next * * music information, contained in the music buffer $C83F-$C84C, and * * updates only those registers which differ from the last data written * * to the sound chip. * * * * ENTRY DP = $D0 * * * * D-reg, X-reg, U-reg trashed * *-----------------------------------------------------------------------* F289=8EC800 Do_Sound: LDX #Vec_Snd_Shadow point to shadow memory F28C CEC83F Do_Sound_x: LDU #Vec_Music_Work point to sound buffer F28F 860D LDA #$0D init count for 14 registers F291=E6C0 LF291 LDB ,U+ get next register F293 E186 CMPB A,X skip if unchanged F295 2702 BEQ LF299 F297 8DC0 BSR Sound_Byte_x else update register F299=4A LF299 DECA go back for next register F29A 2AF5 BPL LF291 F29C 39 RTS *-----------------------------------------------------------------------* * F29D Intensity_1F * * F2A1 Intensity_3F * * F2A5 Intensity_5F * * F2A9 Intensity_7F * * F2AB Intensity_a * * * * Each of these routines are responsible for setting the vector/dot * * intensity (commonly used to denote the z axis) to a specific value. * * 0x00 is the lowest intensity, and 0xFF is the brightest intensity. * * The intensity must be reset to the desired value after each call * * to Wait_Recal; however, it can also be changed at any other time. * * A copy of the new intensity value is saved in $C827. * * * * ENTRY DP = $D0 * * A-reg = intensity (Intensity_a only) * * * * D-reg trashed * *-----------------------------------------------------------------------* F29D=861F Intensity_1F: LDA #$1F F29F 200A BRA Intensity_a F2A1=863F Intensity_3F: LDA #$3F F2A3 2006 BRA Intensity_a F2A5=865F Intensity_5F: LDA #$5F F2A7 2002 BRA Intensity_a F2A9=867F Intensity_7F: LDA #$7F F2AB=9701 Intensity_a: STA 0 * * is encountered; at that point, it will reset the zero reference * * (the integrators). * * * * ENTRY DP = $D0 * * X-reg points to the dot list * * * * EXIT: X-reg points to next byte after the terminator * * * * D-reg trashed * *-----------------------------------------------------------------------* F2DE=A680 Dot_List_Reset: LDA ,X+ get mode byte F2E0 2E72 BGT Reset0Ref if >0 go to Reset0Ref F2E2 8DDD BSR Dot_ix plot the dot F2E4 20F8 BRA Dot_List_Reset dot_list@x_&_reset *-----------------------------------------------------------------------* * F2E6 Recalibrate * * * * Recalibrate the vector generators. * * * * ENTRY DP = $D0 * * * * D-reg, X-reg trashed * *-----------------------------------------------------------------------* F2E6=8EF9F0 Recalibrate: LDX #Recal_Points $7F7F F2E9 8D1D BSR Moveto_ix_FF F2EB BDF36B JSR Reset0Int F2EE 8D20 BSR Moveto_ix $8080 F2F0 2062 BRA Reset0Ref *-----------------------------------------------------------------------* * F2F2 Moveto_x_7F * * * * This routine forces the scale factor to 0x7F, and then moves the * * pen to the location pointed to by the X register. The relative y * * and relative x coordinates are both 2 byte quantities; however, * * only the most signicant byte of each is of any interest. The values * * pointed to by the X register have the following format: * * * * X => (rel y hi),(rel y lo), (rel x hi), (rel x lo) * * * * The position moved to is obtained by y=(0,x) & x=(2,x). * * * * ENTRY DP = $D0 * * X-reg points to double-sized coordinate pair * * * * D-reg trashed * *-----------------------------------------------------------------------* F2F2=C67F Moveto_x_7F: LDB #$7F Set scale factor to $7F F2F4 D704 STB 9, then the infinity symbol is displayed. * * * * Note: This routine uses bytes at a negative offset from the stack as * * temporary storage, so hopefully an IRQ won't happen until the * * string is finished bring printed! * * * * ENTRY DP = $D0 * * A-reg = ship icon character * * B-reg = number of ships * * X-reg = (y,x) coordinates (Print_Ships only) * * X-reg points to (y,x) coordinates (Print_Ships_x only) * * * * D-reg, X-reg, U-reg trashed * *-----------------------------------------------------------------------* F391=AE84 Print_Ships_x: LDX ,X F393=3404 Print_Ships: PSHS B Save B-reg F395 C680 LDB #$80 F397 3378 LEAU -8,S Point U into the stack F399 3606 PSHU D Save A-reg and a terminator F39B 3502 PULS A Get back B-reg F39D 8109 CMPA #$09 If B-reg >9 then F39F 2302 BLS LF3A3 F3A1 863C LDA #$6C-$30 load $6C = infinty symbol F3A3=8B30 LF3A3 ADDA #$30 F3A5 C62D LDB #'-' F3A7 3606 PSHU D Push digit and minus sign F3A9 3610 PSHU X Push (y,x) coordinates F3AB 20CB BRA Print_Str_yx Print it *-----------------------------------------------------------------------* * F3AD Mov_Draw_VLc_a * * * * This routine moves to the first location specified in vector list, * * and then draws lines between the rest of coordinates in the list. * * The number of vectors to draw is specified as the first byte in the * * vector list. The current scale factor is used. The vector list has * * the following format: * * * * count, rel y, rel x, rel y, rel x, ... * * * * ENTRY DP = $D0 * * X-reg points to the vector list * * * * EXIT: X-reg points to next byte after list * * * * D-reg trashed * *-----------------------------------------------------------------------* F3AD=A680 Mov_Draw_VLc_a: LDA ,X+ F3AF 2008 BRA Draw_VL_a *-----------------------------------------------------------------------* * F3B1 Mov_Draw_VL_b * * * * This routine moves to the first location specified in vector list, * * and then draws lines between the rest of coordinates in the list. * * The vector list has the following format: * * * * rel y, rel x, rel y, rel x, ... * * * * ENTRY DP = $D0 * * B-reg = scale factor * * $C823 = number of vectors to draw * * X-reg points to the vector list * * * * EXIT: $C823 is cleared * * * * EXIT: X-reg points to next byte after list * * * * D-reg trashed * *-----------------------------------------------------------------------* F3B1=D704 Mov_Draw_VL_b: STB D00A, B->D005 *-----------------------------------------------------------------------* * F3CE Draw_VLc * * * * This routine draws vectors between the set of (y,x) points pointed * * to by the X register. The number of vectors to draw is specified * * as the first byte in the vector list. The current scale factor is * * used. The vector list has the following format: * * * * count, rel y, rel x, rel y, rel x, ... * * * * ENTRY DP = $D0 * * X-reg points to the vector list * * * * EXIT: X-reg points to next byte after list * * * * D-reg trashed * *-----------------------------------------------------------------------* F3CE=A680 Draw_VLc: LDA ,X+ F3D0 2008 BRA Draw_VL_a *-----------------------------------------------------------------------* * F3D2 Draw_VL_b * * * * This routine draws vectors between the set of (y,x) points pointed to * * by the X register. The vector list has the following format: * * * * rel y, rel x, rel y, rel x, ... * * * * ENTRY DP = $D0 * * B-reg = the scale factor * * X-reg points to the vector list * * * * EXIT: X-reg points to next byte after list * * * * D-reg trashed * *-----------------------------------------------------------------------* F3D2=D704 Draw_VL_b: STB 1 draw to specified endpoint * * * * ENTRY DP = $D0 * * X-reg points to the vector list * * $C829 contains the line pattern. * * * * EXIT: X-reg points to next byte after terminator * * * * D-reg trashed * *-----------------------------------------------------------------------* F46E=B6C824 Draw_VL_mode: LDA Vec_0Ref_Enable Save old Check0Ref flag F471 3402 PSHS A F473 7FC824 CLR Vec_0Ref_Enable Don't reset the zero reference yet F476=A680 LF476 LDA ,X+ Get the next mode byte F478 2A04 BPL LF47E F47A 8DBB BSR Draw_Pat_VL If <0, draw a patterned line F47C 20F8 BRA LF476 F47E=2605 LF47E BNE LF485 F480 BDF3BC JSR Mov_Draw_VL If =0, move to the next point F483 20F1 BRA LF476 F485=4A LF485 DECA F486 2705 BEQ LF48D F488 BDF3DD JSR Draw_VL If <>1, draw a solid line F48B 20E9 BRA LF476 F48D=3502 LF48D PULS A If =1, exit F48F B7C824 STA Vec_0Ref_Enable Restore old Check0Ref flag F492 7EF34F JMP Check0Ref Reset zero reference if necessary *-----------------------------------------------------------------------* * F495 Print_Str * * * * This is the routine which does the actual printing of a string. The * * U register points to the start of the string, while $C82A contains * * the height of the character, cell, and $C82B contains the width of * * the character cell. The string is terminated with an 0x80. * * * * The string is displayed by drawing 7 horizontal rows of dots. The * * first row is drawn for each character, then the second, etc. The * * character generation table is located at ($F9D4 + $20). Only * * characters 0x20-0x6F (upper case) are defined; the lower case * * characters a-o produce special icons. * * * * ENTRY DP = $D0 * * U-reg points to the start of the string * * * * EXIT: U-reg points to next byte after terminator * * * * D-reg, X-reg trashed * *-----------------------------------------------------------------------* F495=FFC82C Print_Str: STU Vec_Str_Ptr Save string pointer F498 8EF9D4 LDX #Char_Table-$20 Point to start of chargen bitmaps F49B CC1883 LDD #$1883 $8x = enable RAMP? F49E 0F01 CLR PB7 enabled F50E 7EF354 JMP Reset0Ref Reset the zero reference *-----------------------------------------------------------------------* * F511 Random_3 * * F517 Random * * * * This routine generates a random 1-byte number, and places it in the * * A register. Random_3 runs through the random number generator * * algorithm three times. The random number seed is stored in the * * three bytes pointed to by $C87B. * * * * EXIT: A-reg contains the generated random number * * * * All other registers are preserved. * *-----------------------------------------------------------------------* F511=3414 Random_3: PSHS B,X F513 C602 LDB #$02 F515 2003 BRA LF51A F517=3414 Random: PSHS B,X F519 5F CLRB F51A=BEC87B LF51A LDX Vec_Seed_Ptr F51D=A601 LF51D LDA 1,X F51F 49 ROLA F520 49 ROLA F521 49 ROLA F522 49 ROLA F523 A802 EORA 2,X F525 46 RORA F526 6984 ROL ,X F528 6901 ROL 1,X F52A 6902 ROL 2,X F52C 5A DECB F52D 2AEE BPL LF51D F52F A684 LDA ,X F531 3594 PULS B,X,PC *-----------------------------------------------------------------------* * F533 Init_Music_Buf * * * * This routine clears out the music work buffer, located at * * $C83F-$C84C. * * * * X-reg, D-reg trashed * *-----------------------------------------------------------------------* F533=C60D Init_Music_Buf: LDB #$0D F535 8EC83F LDX #Vec_Music_Work F538 8D05 BSR Clear_x_b F53A 863F LDA #$3F F53C A706 STA 6,X F53E 39 RTS *-----------------------------------------------------------------------* * F53F Clear_x_b * * * * This routine clears to 0 the block of memory starting at the * * address contained in the X register, and continuing for the number * * of bytes specified by B+1. * * * * ENTRY X-reg points to the start of the RAM to be cleared. * * B-reg = number of bytes minus 1 to clear. * * * * EXIT: D-reg = $FFFF * *-----------------------------------------------------------------------* F53F=4F Clear_x_b: CLRA F540 2006 BRA Clear_x_d *-----------------------------------------------------------------------* * F542 Clear_C8_RAM (never used by GCE carts?) * * * * This routine clears to 0 the block of memory in the range * * $C800-$C8FF. * * * * EXIT: X-reg = $C800 * * D-reg = $FFFF * *-----------------------------------------------------------------------* F542=8EC800 Clear_C8_RAM: LDX #$C800 *-----------------------------------------------------------------------* * F545 Clear_x_256 * * F548 Clear_x_d * * * * This routine clears the block of memory starting at the contained * * in the X register to zero. * * * * ENTRY X-reg points to the start of RAM to be cleared * * D-reg = number of bytes to clear minus 1 (Clear_x_d only) * * * * EXIT: D-reg = $FFFF * *-----------------------------------------------------------------------* F545=CC00FF Clear_x_256: LDD #$00FF F548=6F8B Clear_x_d: CLR D,X F54A 830001 SUBD #$0001 F54D 2AF9 BPL Clear_x_d F54F 39 RTS *-----------------------------------------------------------------------* * F550 Clear_x_b_80 * * F552 Clear_x_b_a * * * * This routine sets the block of memory pointed to by the X register * * to $80 or the A register. The B register specifies the number of * * bytes to be cleared. * * * * ENTRY A-reg = byte to be stored (Clear_x_b_a only) * * B-reg = number of bytes to clear ($00 = 256) * * X-reg points to start of memory block to clear * * * * EXIT: A-reg = $80 (Clear_x_b_80 only) * * B-reg = $00 * * * * All other registers preserved. * *-----------------------------------------------------------------------* F550=8680 Clear_x_b_80: LDA #$80 F552=A785 Clear_x_b_a: STA B,X F554 5A DECB F555 26FB BNE Clear_x_b_a F557 A784 STA ,X F559 39 RTS *-----------------------------------------------------------------------* * F55A Dec_3_Counters * * F55E Dec_6_Counters * * * * These routines check either the first three or all * six of the default counters at $C82E-$C833 and * decrements those which are not already zero. * * * EXIT: X-reg points to the default counters at $C82E * B-reg = $FF * * * * All other registers preserved. * *-----------------------------------------------------------------------* F55A=C602 Dec_3_Counters: LDB #$02 F55C 2002 BRA LF560 F55E=C605 Dec_6_Counters: LDB #$05 F560=8EC82E LF560 LDX #Vec_Counters *-----------------------------------------------------------------------* * F563 Dec_Counters * * * * This routine checks the counters pointed to by the X register and * * decrements those which are not already zero. * * * * ENTRY B-reg = number of counters minus 1 * * X-reg points to counter bytes * * * * EXIT: B-reg = $FF * * * * All other registers preserved. * *-----------------------------------------------------------------------* F563=6D85 Dec_Counters: TST B,X F565 2702 BEQ LF569 F567 6A85 DEC B,X F569=5A LF569 DECB F56A 2AF7 BPL Dec_Counters F56C 39 RTS *-----------------------------------------------------------------------* * F56D Delay_3 30 cycles * * F571 Delay_2 25 cycles * * F575 Delay_1 20 cycles * * F579 Delay_0 12 cycles * * F57A Delay_b 5*B + 10 cycles * * F57D Delay_RTS 5 cycles * * * * Each of these routines loads the B-register with the indicated * * value, and then loops until the B register value has decremented * * below zero. Delay_RTS is just an RTS instruction, but at least * * one GCE cartridge calls it. * * * * Cycle counts do not include timing of the instructions used to * * call the delay routines. * * * * ENTRY B-reg = delay count (Delay_b only) * * * * EXIT: B-reg = $FF (except Delay_RTS) * *-----------------------------------------------------------------------* F56D=C603 Delay_3: LDB #$03 2 cycles F56F 2009 BRA Delay_b 3 cycles F571=C602 Delay_2: LDB #$02 2 cycles F573 2005 BRA Delay_b 3 cycles F575=C601 Delay_1: LDB #$01 2 cycles F577 2001 BRA Delay_b 3 cycles F579=5F Delay_0: CLRB 2 cycles F57A=5A Delay_b: DECB 2 cycles F57B 2AFD BPL Delay_b 3 cycles F57D 39 Delay_RTS: RTS 5 cycles *-----------------------------------------------------------------------* * F57E Bitmask_a * * * * This routine takes a bit number, specified in the A register, and * * returns a bit mask with only the specified bit set. * * * * ENTRY A-reg contains the bit number * * * * EXIT: A-reg contains the bit mask * * * * X-reg trashed * *-----------------------------------------------------------------------* F57E=8EF9DC Bitmask_a: LDX #Bit_Masks F581 A686 LDA A,X F583 39 RTS *-----------------------------------------------------------------------* * F584 Abs_a_b * * F58B Abs_b * * * * This routine returns the absolute value of the two single byte * * numbers passed in in the A and B registers. Abs_b only uses the B * * register. There is a special case: 0x80 is returned as 0x7F. * * * * ENTRY A-reg contains first value * * B-reg contains second value (Abs_a_b only) * * * * EXIT: A-reg contains absolute value of first value * * B-reg contains absolute value of second value (Abs_a_b only) * * * * All other registers preserved. * *-----------------------------------------------------------------------* F584=4D Abs_a_b: TSTA F585 2A04 BPL Abs_b F587 40 NEGA F588 2801 BVC Abs_b F58A 4A DECA F58B=5D Abs_b TSTB F58C 2A04 BPL LF592 F58E 50 NEGB F58F 2801 BVC LF592 F591 5A DECB F592=39 LF592 RTS *-----------------------------------------------------------------------* * F593 Rise_Run_Angle * * * * Given a (rise,run) pair, this routine calculates the angle which * * corresponds to that (rise,run) pair. The returned angle is relative * * to the x-axis (+ is CCW), so to convert it to a Vectrex angle * * (relative to the y-axis, + is CCW), you must subtract the number 0x10 * * (90 degrees) from the returned value. * * * * ENTRY DP = $C8 * * A-reg = rise value * * B-reg = run value * * * * EXIT: A-reg = the angle from the x-axis * * B-reg = the angle from the x-axis * * * * All other registers preserved. * *-----------------------------------------------------------------------* F593=3410 Rise_Run_Angle: PSHS X F595 DD34 STD positive rise, not on an axis, or * * negative run, not on an axis. * * 0x80 => negative rise, not on an axis, or * * positive run, not on an axis. * * 1 => positive rise, on an axis, or * * negative run, on an axis. * * 0x81 => negative rise, on an axis, or * * positive run, on an axis. * * * * ENTRY A-reg = the angle value * * * * EXIT: A-reg = slope? * * B-reg = slope direction? * * * * X-reg trashed * *-----------------------------------------------------------------------* F5D9=8B10 Get_Rise_Idx: ADDA #$10 Offset angle by 90 degrees F5DB=8EFC6D Get_Run_Idx: LDX #DFC6D Get address of slope table F5DE 5F CLRB F5DF 8520 BITA #$20 If angle in 180-360, F5E1 2702 BEQ LF5E5 F5E3 C680 LDB #$80 flag negative rise or positive run F5E5=841F LF5E5 ANDA #$1F Mask to multiple of 180 degrees F5E7 8110 CMPA #$10 If 90 degrees F5E9 2601 BNE LF5EC F5EB 5C INCB then rise or run is on an axis F5EC=A686 LF5EC LDA A,X Get slope from slope table F5EE 39 RTS *-----------------------------------------------------------------------* * F5EF Get_Rise_Run * * * * This routine gets the index pair for both the rise and run, using * * the passed-in angle value. * * * * ENTRY DP = $C8 * * $C836 contains the angle value * * * * EXIT: $C837-$C838 contains the index pair for the run * * $C839-$C83A contains the index pair for the rise * * * * D-reg trashed * *-----------------------------------------------------------------------* F5EF=3410 Rise_Run_Idx: PSHS X Save X-reg F5F1 9636 LDA $C84F 32 nibble ADSR table * * header word -> $C851 8-byte "twang" table * * data bytes * * * * The ADSR table is simply 32 nibbles (16 bytes) of amplitude values. * * * * The twang table is 8 signed bytes to modify the base frequency of * * each note being played. Each channel has a different limit to its * * twang table index (6-8) to keep them out of phase to each other. * * * * Music data bytes: * * Bits 0-5 = frequency * * Bit 6 clear = tone * * Bit 6 set = noise * * Bit 7 set = next music data byte is for next channel * * Bit 7 clear, play note with duration in next music data byte: * * bits 0-5 = duration * * bit 6 = unused * * bit 7 set = end of music * * * * ENTRY DP = $C8 * * U-reg points to the start of the music data * * $C84D points to note table (Init_Music_dft only) * * C856 may need to be set. * * * * D-reg, X-reg, Y-reg, U-reg trashed * *-----------------------------------------------------------------------* F687=9656 Init_Music_chk: LDA =$80, advance to next channel F73E E680 LDB ,X+ Get second byte of music data F740 2A06 BPL LF748 If >=$80, (terminator) F742 BDF533 JSR Init_Music_Buf clear music buffer, F745 0F56 CLR 0 add twang to base frequency F78A 8900 ADCA #$00 Propagate carry to high byte F78C=ED81 LF78C STD ,X++ Store freq in regs 5/4, 3/2, 1/0 F78E 8CC84D CMPX #Vec_Music_Work+14 F791 26E5 BNE LF778 F793=39 LF793_RTS RTS *-----------------------------------------------------------------------* * F7A9 Select_Game * * * * This routine provides a game with the means for allowing the player * * to choose the game number he would like to play, and the number of * * players. The game indicates the number of game versions available, * * by placing the value in the B register. The number of players * * allowed is specified in the A register. If a parameter is passed in * * with a value of 0, then the corresponding question will not be asked. * * The number of players selected is returned in $C879, while the game * * number selected is returned in $C87A. * * * * This routine performs most of the work involved in allowing the * * player to select a game version and the number of players. It * * displays the game # and player options, and allows the player a * * certain amount of time to modify their values. Anytime one of the * * buttons is used to modify a value, the timer will be restarted. * * When a button is pressed, the associated value is modified, * * and then redisplayed on the screen. This routine will return when * * either the timer expires, or button 4 is pressed. * * * * ENTRY A-reg = maximum number of players allowed * * B-reg = number of game versions available * * * * EXIT: DP = $C8 * * $C879 contains number of players selected * * $C87A contains the game version selected * * * * D-reg, X-reg, Y-reg trashed * *-----------------------------------------------------------------------* F794=20C0 Player_Str: FDB $20C0 F796 40C0 FDB $40C0 F798 504C415945 FCC /PLAYER/ F79E 80 FCB $80 F79F=E0C0 Game_Str: FDB $E0C0 F7A1 01C0 FDB $01C0 F7A3 2047414D45 FCC / GAME/ F7A8 80 FCB $80 F7A9=FDC84F Select_Game: STD Vec_Max_Players Save max players and games F7AC 4D TSTA If non-zero players specified, F7AD 2702 BEQ LF7B1 F7AF 8601 LDA #$01 set selection to 1 F7B1=5D LF7B1 TSTB If non-zero games specified, F7B2 2702 BEQ LF7B6 F7B4 C601 LDB #$01 set selection to 1 F7B6=FDC879 LF7B6 STD Vec_Num_Players Save default selection F7B9 BDF1AF JSR DP_to_C8 DP to RAM F7BC CCF850 LDD #$F850 F7BF DD2A STD U score: a = 1 * * 3) U score > X score: a = 2 * * * * ENTRY X-reg points to first score string (terminated with $80) * * U-reg points to second score string * * * * EXIT: A-reg returns result fo the compare * * * * B-reg trashed * *-----------------------------------------------------------------------* F8C7=3450 Compare_Score: PSHS X,U Save score pointers F8C9 4F CLRA Default to scores are the same F8CA=E680 LF8CA LDB ,X+ F8CC 2B08 BMI LF8D6 Return if end of string F8CE E1C0 CMPB ,U+ F8D0 27F8 BEQ LF8CA Continue if byte is the same F8D2 2201 BHI LF8D5 Return 1 if X > U F8D4 4C INCA Return 2 if U > X F8D5=4C LF8D5 INCA F8D6=35D0 LF8D6 PULS X,U,PC Restore pointers and return *-----------------------------------------------------------------------* * F8D8 New_High_Score * * * * This routine compares a players score string, pointed to by the * * X register, to the current hi score, pointed by the U register. If * * the player's score is higher than the currently saved hi score, then * * the player's score will be copied into the hi score buffer pointed * * to by the U register. * * * * ENTRY X-reg points to a player's score string * * U-reg points to the high score string (usually $CBEB?) * * * * X-reg, U-reg, D-reg trashed * *-----------------------------------------------------------------------* F8D8=8DED New_High_Score: BSR Compare_Score Compare the scores F8DA 8101 CMPA #$01 F8DC 2606 BNE LF8E4 Return if X is not > U F8DE=A680 LF8DE LDA ,X+ Copy the new high score F8E0 A7C0 STA ,U+ F8E2 2AFA BPL LF8DE until end of string encountered F8E4=39 LF8E4 RTS *-----------------------------------------------------------------------* * F8E5 Obj_Will_Hit_u * * F8F3 Obj_Will_Hit * * * * This routine first modifies the position of the object, and then it * * checks to see if the missile has hit the object. The Y register * * contains the (y,x) position of the object, the U register contains * * a pointer to the (y,x) modification values, the X register contains * * the missile (y,x) position, and the D register contains the * * (height/2, width/2) of the object. * * * * (0,u) is temporarily added to the y position of the object, and * * (1,u) is temporarily added to the x position. * * * * ENTRY Y-reg = (y,x) position of the object * * X-reg = (y,x) position of the missile * * U-reg points to movement (y,x) (Mov_Obj_Hit_u only) * * U-reg = movement (y,x) (Mov_Obj_Hit only) * * D-reg = (h/2,w/2) size of object * * * * EXIT: Carry bit set if the object & missile have collided * * * * ALL registers saved. Even the original Y-register. * *-----------------------------------------------------------------------* F8E5=3420 Obj_Will_Hit_u: PSHS Y Save regs for the hit-test code F8E7 3436 PSHS D,X,Y F8E9 EC64 LDD 4,S Get object position F8EB ABC4 ADDA ,U Add it to the modification values F8ED EB41 ADDB 1,U F8EF=ED64 LF8EF STD 4,S Put updated object position back F8F1 2010 BRA LF903 Go do the hit-test F8F3=3420 Obj_Will_Hit: PSHS Y Save regs for the hit-test code F8F5 3436 PSHS D,X,Y F8F7 1F30 TFR U,D Get modification values F8F9 AB64 ADDA 4,S Add them to the object position F8FB EB65 ADDB 5,S F8FD 20F0 BRA LF8EF Put update position back and hit-test *-----------------------------------------------------------------------* * F8FF Obj_Hit * * * * Thit routine checks to see if a missile hashit an object. If the * * missile has hit the object, then the carry bit will be set; * * otherwise, the carry bit will be cleared. A hit is checked for in * * the following fashion: * * * * if (object y-height/2) <= missile y <= (object y+height/2) * * and * * (object x-width/2) <= missile x <= (object x+width/x) * * * * then the missile hit, otherwise it missed. * * * * ENTRY Y-reg = (y,x) position of the object * * X-reg = (y,x) position of the missile * * D-reg = (h/2,w/2) size of object * * * * EXIT: Carry bit set if the object & missile have collided * * * * All registers preserved. * *-----------------------------------------------------------------------* F8FF=3420 Obj_Hit: PSHS Y Save some regs F901 3436 PSHS D,X,Y F903=1F41 LF903 TFR S,X Point X to the stack F905 5F CLRB Offset to point to y F906=3A LF906 ABX F907 A604 LDA 4,X Get height/2 F909 AB84 ADDA ,X Add object y F90B 2802 BVC LF90F F90D 867F LDA #$7F Set to $7F if overflow F90F=A102 LF90F CMPA 2,X Branch if missile out of range F911 2D15 BLT LF928 F913 A604 LDA 4,X Get height/2 F915 A084 SUBA ,X Subtract object y F917 2802 BVC LF91B F919 8680 LDA #$80 Set to $80 if overflow F91B=A102 LF91B CMPA 2,X Branch if missile out of range F91D 2E09 BGT LF928 F91F 5C INCB Offset to point to x F920 C102 CMPB #$02 F922 25E2 BCS LF906 Go back for x F924 1A01 ORCC #$01 Object in range, set carry F926 2002 BRA LF92A F928=1CFE LF928 ANDCC #$FE Object not in range, clear carry F92A=3536 LF92A PULS D,X,Y F92C 35A0 PULS Y,PC *-----------------------------------------------------------------------* * F92E Explosion_Snd * * * * This routine appears to generate some type of an explosion sound, * * dependent upon the 4 bytes which are pointed to by the U register. * * You will probably need to call Do_Sound for this to do anything. * * * * The format of the 4-byte block is: * * 1) Bits 0-2 = ? Stored in $C85D * * Bits 3-5 = ? Stored in $C853 * * Bits 6-7 = 0 * * Bits 0-2 and 3-5 are ORed and stored in bits 0-2 of * * $C854 * * 2) <0 = ? Something to do with register 6 * * =0 = ? * * >0 = ? * * 3) <0 = ? * * =0 = ? * * >0 = ? * * 4) Speed? Higher values = lower duration? * * * * ENTRY DP = $C8 * * U-reg points to 4-byte block of data if $C867 high bit set * * * * D-reg, X-reg trashed * *-----------------------------------------------------------------------* F92E=9667 Explosion_Snd: LDA