; 4 KB Bios ; can be assembled correctly now ; corrected and compatibilty added by Malban ; ; assemble with comand line: ; .\ass\as09.exe -w200 -h0 -l -mcti bios.asm >error ; ; used the 6809 assembler: ; as09 [1.11]. ; Copyright 1990-1994, Frank A. Vorstenbosch, Kingswood Software. ; Available at: ; http://www.falstaff.demon.co.uk/cross.html ; CODE ORG $F000 DATA ORG $F000 BSS ORG $F000 CODE ;-----------------------------------------------------------------------; ; 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. ; ;-----------------------------------------------------------------------; Start: LDS #Vec_Default_Stk ;Set up stack pointer JSR Init_OS ;Initialize system LDD #$7321 ;Check cold start flag CMPD Vec_Cold_Flag BEQ Warm_Start ;Branch if warm start STD Vec_Cold_Flag ;Initialize cold start flag INC $C83B ;Set high score invalid flag LDX #Vec_High_Score ;Clear high score JSR Clear_Score ; First power-up loop. This prints the "VECTREX" ; power-on screen and plays the power-on music. LF01C: JSR DP_to_C8 ;DP to RAM LDD PB7 enabled 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 ; ;-----------------------------------------------------------------------; Joy_Analog: DEC $C823 ;Set analog mode flag Joy_Digital: LDX #Vec_Joy_Mux_1_X;Point to first pot LF1FB: LDA ,X+ ;Read it if enabled BNE LF20B LF1FF: CMPX #$C823 ;Go back untl all pots read BNE LF1FB CLR ,X ;X points to $C823, clear it LDA #$01 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 ; ;-----------------------------------------------------------------------; Sound_Bytes: LDX #Vec_Snd_Shadow ;Point to shadow memory BRA Sound_Bytes_x LF282: BSR Sound_Byte_x ;Update the sound register Sound_Bytes_x: LDD ,U++ ;Get next next pair of bytes BPL LF282 ;Go back if not end of list 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 ; ;-----------------------------------------------------------------------; Do_Sound: LDX #Vec_Snd_Shadow ;point to shadow memory Do_Sound_x: LDU #Vec_Music_Work ;point to sound buffer LDA #$0D ;init count for 14 registers LF291: LDB ,U+ ;get next register CMPB A,X ;skip if unchanged BEQ LF299 BSR Sound_Byte_x ;else update register LF299: DECA ;go back for next register BPL LF291 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 ; ;-----------------------------------------------------------------------; Intensity_1F: LDA #$1F BRA Intensity_a Intensity_3F: LDA #$3F BRA Intensity_a Intensity_5F: LDA #$5F BRA Intensity_a Intensity_7F: LDA #$7F 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 ; ;-----------------------------------------------------------------------; Dot_List_Reset: LDA ,X+ ;get mode byte BGT Reset0Ref ;if >0 go to Reset0Ref BSR Dot_ix ;plot the dot BRA Dot_List_Reset ;dot_list@x_&_reset ;-----------------------------------------------------------------------; ; F2E6 Recalibrate ; ; ; ; Recalibrate the vector generators. ; ; ; ; ENTRY DP = $D0 ; ; ; ; D-reg, X-reg trashed ; ;-----------------------------------------------------------------------; Recalibrate: LDX #Recal_Points ;$7F7F BSR Moveto_ix_FF JSR Reset0Int BSR Moveto_ix ;$8080 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 ; ;-----------------------------------------------------------------------; Moveto_x_7F: LDB #$7F ;Set scale factor to $7F STB Moveto_d_7F opt JSR Delay_1 JMP Print_Str ;-----------------------------------------------------------------------; ; F385 Print_List_hw ; ; ; ; This displays the group of strings described by the parameter block ; ; which is pointed to by the U register. The string parameter block ; ; has the following format: ; ; ; ; height, width, rel y, rel x, string, 0x80, ; ; height, width, rel y, rel x, string, 0x80, ; ; 0x00 ; ; ; ; ENTRY DP = $D0 ; ; U-reg points to string list ; ; ; ; EXIT: U-reg points to null terminator byte ; ; ; ; D-reg, X-reg trashed ; ;-----------------------------------------------------------------------; LF383: BSR Print_Str_hwyx Print_List_hw: LDA ,U BNE LF383 RTS ;-----------------------------------------------------------------------; ; F38A Print_List ; ; F38C Print_List_chk ; ; ; ; This displays the group of strings described by the parameter block ; ; which is pointed to by the U register. The string parameter block ; ; has the following format: ; ; ; ; rel y, rel x, string, 0x80, ; ; rel y, rel x, string, 0x80, ; ; 0x00 ; ; ; ; The current string height and width to which the hardware is set will ; ; be used. ; ; ; ; Print_List routine will first print the passed-in string, and THEN ; ; check for the end of the string list. Print_List_Chk will check for ; ; the end of the string list first. ; ; ; ; ENTRY DP = $D0 ; ; U-reg points to string list ; ; ; ; EXIT: U-reg points to null terminator byte ; ; ; ; D-reg, X-reg trashed ; ;-----------------------------------------------------------------------; Print_List: BSR Print_Str_yx Print_List_Chk: LDA ,U BNE Print_List RTS ;-----------------------------------------------------------------------; ; F391 Print_Ships_x ; ; F393 Print_Ships ; ; ; ; This routine displays the number of ships passed in the B register ; ; followed by a minus sign and the ship icon character passed in the ; ; A register at the (y,x) coordinates passed in the X register. If ; ; the B-register > 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 ; ;-----------------------------------------------------------------------; Print_Ships_x: LDX ,X Print_Ships: PSHS B ;Save B-reg LDB #$80 LEAU -8,S ;Point U into the stack PSHU D ;Save A-reg and a terminator PULS A ;Get back B-reg CMPA #$09 ;If B-reg >9 then BLS LF3A3 LDA #$6C-$30 ;load $6C = infinty symbol LF3A3: ADDA #$30 LDB #'-' PSHU D ;Push digit and minus sign PSHU X ;Push (y,x) coordinates 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 ; ;-----------------------------------------------------------------------; Mov_Draw_VLc_a: LDA ,X+ BRA Mov_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 ; ;-----------------------------------------------------------------------; 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 ; ;-----------------------------------------------------------------------; Draw_VLc: LDA ,X+ 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 ; ;-----------------------------------------------------------------------; 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 ; ;-----------------------------------------------------------------------; Draw_VL_mode: LDA Vec_0Ref_Enable ;Save old Check0Ref flag PSHS A CLR Vec_0Ref_Enable ;Don't reset the zero reference yet LF476: LDA ,X+ ;Get the next mode byte BPL LF47E BSR Draw_Pat_VL ;If <0, draw a patterned line BRA LF476 LF47E: BNE LF485 JSR Mov_Draw_VL ;If =0, move to the next point BRA LF476 LF485: DECA BEQ LF48D JSR Draw_VL ;If <>1, draw a solid line BRA LF476 LF48D: PULS A ;If =1, exit STA Vec_0Ref_Enable ;Restore old Check0Ref flag 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 ; ;-----------------------------------------------------------------------; Print_Str: STU Vec_Str_Ptr ;Save string pointer LDX #Char_Table-$20 ;Point to start of chargen bitmaps LDD #$1883 ;$8x = enable RAMP? CLR PB7 enabled 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. ; ;-----------------------------------------------------------------------; Random_3: PSHS B,X LDB #$02 BRA LF51A Random: PSHS B,X CLRB LF51A: LDX Vec_Seed_Ptr LF51D: LDA 1,X ROLA ROLA ROLA ROLA EORA 2,X RORA ROL ,X ROL 1,X ROL 2,X DECB BPL LF51D LDA ,X 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 ; ;-----------------------------------------------------------------------; Init_Music_Buf: LDB #$0D LDX #Vec_Music_Work BSR Clear_x_b LDA #$3F STA 6,X 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 ; ;-----------------------------------------------------------------------; Clear_x_b: CLRA 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 ; ;-----------------------------------------------------------------------; 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 ; ;-----------------------------------------------------------------------; Clear_x_256: LDD #$00FF Clear_x_d: CLR D,X SUBD #$0001 BPL Clear_x_d 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. ; ;-----------------------------------------------------------------------; Clear_x_b_80: LDA #$80 Clear_x_b_a: STA B,X DECB BNE Clear_x_b_a STA ,X 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. ; ;-----------------------------------------------------------------------; Dec_3_Counters: LDB #$02 BRA LF560 Dec_6_Counters: LDB #$05 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. ; ;-----------------------------------------------------------------------; Dec_Counters: TST B,X BEQ LF569 DEC B,X LF569: DECB BPL Dec_Counters 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) ; ;-----------------------------------------------------------------------; Delay_3: LDB #$03 ;2 cycles BRA Delay_b ;3 cycles Delay_2: LDB #$02 ;2 cycles BRA Delay_b ;3 cycles Delay_1: LDB #$01 ;2 cycles BRA Delay_b ;3 cycles Delay_0: CLRB ;2 cycles Delay_b: DECB ;2 cycles BPL Delay_b ;3 cycles 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 ; ;-----------------------------------------------------------------------; Bitmask_a: LDX #Bit_Masks LDA A,X 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. ; ;-----------------------------------------------------------------------; Abs_a_b: TSTA BPL Abs_b NEGA BVC Abs_b DECA Abs_b: TSTB BPL LF592 NEGB BVC LF592 DECB 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. ; ;-----------------------------------------------------------------------; Rise_Run_Angle: PSHS X 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 ; ;-----------------------------------------------------------------------; Get_Rise_Idx: ADDA #$10 ;Offset angle by 90 degrees Get_Run_Idx: LDX #DFC6D ;Get address of slope table CLRB BITA #$20 ;If angle in 180-360, BEQ LF5E5 LDB #$80 ;flag negative rise or positive run LF5E5: ANDA #$1F ;Mask to multiple of 180 degrees CMPA #$10 ;If 90 degrees BNE LF5EC INCB ;then rise or run is on an axis LF5EC: LDA A,X ;Get slope from slope table RTS ;-----------------------------------------------------------------------; ; F5EF Rise_Run_Idx ; ; ; ; 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 ; ;-----------------------------------------------------------------------; Rise_Run_Idx: PSHS X ;Save X-reg 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 frequency table (Init_Music_dft only) ; ; $C856 may need to be set. ; ; ; ; D-reg, X-reg, Y-reg, U-reg trashed ; ;-----------------------------------------------------------------------; Init_Music_chk: LDA =$80, advance to next channel LDB ,X+ ;Get second byte of music data BPL LF748 ;If >=$80, (terminator) JSR Init_Music_Buf ; clear music buffer, CLR 0 add twang to base frequency ADCA #$00 ;Propagate carry to high byte LF78C: STD ,X++ ;Store freq in regs 5/4, 3/2, 1/0 CMPX #Vec_Music_Work+14 BNE LF778 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 ; ;-----------------------------------------------------------------------; Player_Str: FDB $20C0 FDB $40C0 FCC "PLAYER" FCB $80 Game_Str: FDB $E0C0 FDB $01C0 FCC " GAME" FCB $80 Select_Game: STD Vec_Max_Players ;Save max players and games TSTA ;If non-zero players specified, BEQ LF7B1 LDA #$01 ; set selection to 1 LF7B1: TSTB ;If non-zero games specified, BEQ LF7B6 LDB #$01 ; set selection to 1 LF7B6: STD Vec_Num_Players ;Save default selection JSR DP_to_C8 ;DP to RAM LDD #$F850 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 of the compare ; ; ; ; B-reg trashed ; ;-----------------------------------------------------------------------; Compare_Score: PSHS X,U ;Save score pointers CLRA ;Default to scores are the same LF8CA: LDB ,X+ BMI LF8D6 ;Return if end of string CMPB ,U+ BEQ LF8CA ;Continue if byte is the same BHI LF8D5 ;Return 1 if X > U INCA ;Return 2 if U > X LF8D5: INCA 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 ; ;-----------------------------------------------------------------------; New_High_Score: BSR Compare_Score ;Compare the scores CMPA #$01 BNE LF8E4 ;Return if X is not > U LF8DE: LDA ,X+ ;Copy the new high score STA ,U+ BPL LF8DE ;until end of string encountered 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. ; ;-----------------------------------------------------------------------; Obj_Will_Hit_u: PSHS Y ;Save regs for the hit-test code PSHS D,X,Y LDD 4,S ;Get object position ADDA ,U ;Add it to the modification values ADDB 1,U LF8EF: STD 4,S ;Put updated object position back BRA LF903 ;Go do the hit-test Obj_Will_Hit: PSHS Y ;Save regs for the hit-test code PSHS D,X,Y TFR U,D ;Get modification values ADDA 4,S ;Add them to the object position ADDB 5,S 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. ; ;-----------------------------------------------------------------------; Obj_Hit: PSHS Y ;Save some regs PSHS D,X,Y LF903: TFR S,X ;Point X to the stack CLRB ;Offset to point to y LF906: ABX LDA 4,X ;Get height/2 ADDA ,X ;Add object y BVC LF90F LDA #$7F ;Set to $7F if overflow LF90F: CMPA 2,X ;Branch if missile out of range BLT LF928 LDA 4,X ;Get height/2 SUBA ,X ;Subtract object y BVC LF91B LDA #$80 ;Set to $80 if overflow LF91B: CMPA 2,X ;Branch if missile out of range BGT LF928 INCB ;Offset to point to x CMPB #$02 BCS LF906 ;Go back for x ORCC #$01 ;Object in range, set carry BRA LF92A LF928: ANDCC #$FE ;Object not in range, clear carry LF92A: PULS D,X,Y 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 ; ;-----------------------------------------------------------------------; Explosion_Snd: LDA