; 4 KB Bios
; can be assembled correctly now
; corrected and compatibilty added by Christopher Salomon
;
; 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
;-----------------------------------------------------------------------;
; F06C Warm_Start ;
; ;
; Jump here to restart the Vectrex without re-initializing the OS. ;
;-----------------------------------------------------------------------;
; Prepare for ROM check
Warm_Start: JSR DP_to_C8 ;DP to RAM
LDA #$CC ;Set new line pattern
STA
;-----------------------------------------------------------------------;
; F14C Init_VIA ;
; ;
; This routine is invoked during powerup, to initialize the VIA chip. ;
; Among other things, it initializes the scale factor to 0x7F, and ;
; sets up the direction for the port A and B data lines. ;
; ;
; EXIT: DP = $D0 ;
; ;
; D-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
Init_VIA: BSR DP_to_D0
LDD #$9FFF ;Port A=all output
STD PB7 enabled
STA
;-----------------------------------------------------------------------;
; F164 Init_OS_RAM ;
; ;
; This routine first clears the block of RAM in the range $C800 to ;
; $C87A, and then it initializes the dot dwell time, the refresh time, ;
; and the joystick enable flags. ;
; ;
; EXIT: DP = $C8 ;
; ;
; D-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
Init_OS_RAM: BSR DP_to_C8 ;DP to RAM
LDB #$7A ;Clear $C800-$C87A
LDX #$C800
JSR Clear_x_b
LDD #Vec_Random_Seed;Point $C87B to $C87D
STD
;-----------------------------------------------------------------------;
; F18B Init_OS ;
; ;
; This routine is responsible for setting up the initial system state, ;
; each time the system is either reset or powered up. It will ;
; initialize the OS RAM area, initialize the VIA chip, and then clear ;
; all the registers on the sound chip. ;
; ;
; EXIT: DP = $D0 ;
; ;
; D-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
Init_OS: BSR Init_OS_RAM
BSR Init_VIA
JMP Clear_Sound
;-----------------------------------------------------------------------;
; F192 Wait_Recal ;
; ;
; Wait for t2 (the refresh timer) to timeout, then restart it using ;
; the value in $C83D. then, recalibrate the vector generators to the ;
; origin (0,0). This routine MUST be called once every refresh ;
; cycle, or your vectors will get out of whack. This routine calls ;
; Reset0Ref, so the integrators are left in zero mode. ;
; ;
; EXIT: DP = $D0 ;
; ;
; D-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
Wait_Recal: LDX Vec_Loop_Count ;Increment loop counter
LEAX 1,X
STX Vec_Loop_Count
BSR DP_to_D0 ;DP to I/O
LDA #$20
LF19E: BITA
;-----------------------------------------------------------------------;
; F1A2 Set_Refresh ;
; ;
; This routine loads the refresh timer (t2) with the value in $C83D- ;
; $C83E, and recalibrates the vector generators, thus causing the pen ;
; to be left at the origin (0,0). The high order byte for the timer ;
; is loaded from $C83E, and the low order byte is loaded from $C83D. ;
; The refresh rate is calculated as follows: ;
; ;
; rate = (C83E)(C83D) / 1.5 mhz ;
; ;
; ENTRY DP = $D0 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Set_Refresh: LDD $C83D ;Store refresh value
STD
;-----------------------------------------------------------------------;
; F1AA DP_to_D0 ;
; ;
; Sets the DP register to $D0, so that all direct page addressing will ;
; start at $D000 (the hardware I/O area). ;
; ;
; EXIT: DP = $D0 ;
; A-reg = $D0 ;
;-----------------------------------------------------------------------;
DP_to_D0: LDA #$D0
TFR A,DP
RTS
;-----------------------------------------------------------------------;
; F1AF DP_to_C8 ;
; ;
; Sets the DP register to $C8, so that all direct page addressing will ;
; start at $C800 (OS RAM area). ;
; ;
; ;
; EXIT: DP = $C8 ;
; A-reg = $C8 ;
;-----------------------------------------------------------------------;
DP_to_C8: LDA #$C8
TFR A,DP
RTS
;-----------------------------------------------------------------------;
; F1B4 Read_Btns_Mask ;
; F1BA Read_Btns ;
; ;
; Both of these routines read the button states on the two joysticks, ;
; and return their state in the following RAM locations: ;
; ;
; joystick 1, button 1: $C812 = $01 ;
; button 2: $C813 = $02 ;
; button 3: $C814 = $04 ;
; button 4: $C815 = $08 ;
; joystick 2, button 1: $C816 = $10 ;
; button 2: $C817 = $20 ;
; button 3: $C818 = $40 ;
; button 4: $C819 = $80 ;
; ;
; C80F: Contains current state of all buttons; ;
; 1 = depressed, 0 = not depressed ;
; ;
; C810: Contains state of all buttons from LAST time these ;
; routines were called; if Read_Btns_Mask was called, ;
; then this is AND'ed with the passed in mask. ;
; ;
; C811: Contains the same information as $C812-$C819 ;
; ;
; Bit 7 Bit 0 ;
; +-----+-----+-----+-----+-----+-----+-----+-----+ ;
; | 2.4 | 2.3 | 2.2 | 2.1 | 1.4 | 2.3 | 1.2 | 1.1 | ;
; +-----+-----+-----+-----+-----+-----+-----+-----+ ;
; ;
; If Read_Btns is called, the result will be the same as Read_Btns_Mask ;
; with a mask of $FF, and a 1 will only be returned if the button ;
; has transitioned to being pressed. ;
; ;
; If Read_Btns_Mask is called, then a mask, passed in in the A-reg ;
; will be used to determine how the button state info is returned: ;
; ;
; If a bit is 0, then the current state of the button is to be returned ;
; in the appropriate RAM location; 0 = not pressed, and 1 = pressed. ;
; ;
; If a bit is 1, then the appropriate RAM location is set to 1 only ;
; on the depression transition of the button; additional calls will ;
; return 0, until the button is released and then depressed again. ;
; ;
; ENTRY DP = $D0 ;
; A-reg = mask (for Read_Btns_Mask only) ;
; ;
; Exit: A-reg = button transition state (same as $C811) ;
; ;
; B-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
Read_Btns_Mask: ANDA Vec_Btn_State ;Mask out "always" buttons
STA Vec_Btn_State
Read_Btns: LDX #Vec_Button_1_1 ;Point to button flags
LDA -3,X ;Save previous state
STA -2,X
LDA #$0E ;Sound chip register 0E to port A
STA
;-----------------------------------------------------------------------;
; F1F5 Joy_Analog ;
; F1F8 Joy_Digital ;
; ;
; These routines read the current positions of the two joysticks. ;
; ;
; The joystick enable flags (C81F-C822) must be initialized to one of ;
; the following values: ;
; ;
; 0 - ignore; return no value. ;
; 1 - return state of console 1 left/right position. ;
; 3 - return state of console 1 up/down position. ;
; 5 - return state of console 2 left/right position. ;
; 7 - return state of console 2 up/down position. ;
; ;
; The joystick values are returned in $C81B-$C81E, where the value ;
; returned in $C81B corresponds to the mask set in in $C81F, and so ;
; on and so forth. ;
; ;
; The joystick conversion is dependent on which routine is called. ;
; Results for each routine are: ;
; ;
; Joy_Digital: ;
; The return value will be: ;
; < 0 if joystick is left of down of center. ;
; = 0 if joystick is centered. ;
; > 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
;-----------------------------------------------------------------------;
; F256 Sound_Byte ;
; F259 Sound_Byte_x ;
; F25B Sound_Byte_raw ;
; ;
; All of these routines cause a byte of music data to be written to ;
; the music chip. Sound_Byte stores a shadow copy of the data into ;
; $C800-$C80E, and Sound_Byte_x stores a shadow copy into a 15 byte ;
; area pointed to by the X register. Sound_Byte_raw does not store a ;
; shadow copy of the data at all. ;
; ;
; ENTRY DP = $D0 ;
; A-reg = which of the 15 sound chip registers to modify ;
; B-reg = the byte of sound data ;
; X-reg = 15 byte shadow area (Sound_Byte_x only) ;
; ;
; EXIT: X-reg = $C800 (Sound_Byte only) ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Sound_Byte: LDX #Vec_Snd_Shadow ;point to shadow memory
Sound_Byte_x: STB A,X
Sound_Byte_raw: STA
;-----------------------------------------------------------------------;
; F272 Clear_Sound ;
; ;
; This routine clears the 15 registers on the music chip and the soft ;
; copy of their values (C800-C80E), by writing a byte of 0 to each ;
; register. This causes the sound chip to not make any sounds. ;
; ;
; ENTRY DP = $D0 ;
; ;
; D-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
Clear_Sound: LDD #$0E00
LF275: BSR Sound_Byte
DECA
BPL LF275
JMP Init_Music_Buf
;-----------------------------------------------------------------------;
; F27D Sound_Bytes ;
; F284 Sound_Bytes_x? (apparently never used) ;
; ;
; This routine copies a block of sound information into the sound ;
; chip buffer (at $C800-$C80E) and into the registers on the music ;
; chip. The format for the block of sound data is as follows: ;
; ;
; (register number), (music data), ;
; (register number), (music data), ;
; . . ;
; . . ;
; 0xFF ;
; ;
; As long as the register number is >= 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
;-----------------------------------------------------------------------;
; F2BE Dot_ix_b ;
; F2C1 Dot_ix ;
; ;
; These routines draw a dot at the relative y and relative x ;
; position pointed to by the X register. Afterwards, the X register ;
; is incremented by 2. ;
; ;
; ENTRY DP = $D0 ;
; X-reg points to the (y,x) coordinate pair ;
; B-reg contains the intensity (Dot_ix_b only) ;
; $C828 contains the intensity (Dot_ix only) ;
; ;
; EXIT X-reg incremented by 2 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Dot_ix_b: STB Vec_Dot_Dwell
Dot_ix: LDD ,X++
;-----------------------------------------------------------------------;
; F2C3 Dot_d ;
; ;
; This routine draws a dot at the relative y and relative x position ;
; contained in the D register. The intensity used is the value ;
; already stored in $C828. ;
; ;
; ENTRY DP = $D0 ;
; A-reg = relative Y coordinate ;
; B-reg = relative X coordinate ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Dot_d: BSR Moveto_d
;-----------------------------------------------------------------------;
; F2C5 Dot_here ;
; ;
; This routine draws a dot at the current pen position. ;
; The intensity used is the value already stored in $C828. ;
; ;
; ENTRY DP = $D0 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Dot_here: LDA #$FF ;Set pattern to all 1's
STA
;-----------------------------------------------------------------------;
; F2D5 Dot_List ;
; ;
; This routine draws a series of dots, using the intensity already ;
; set up in $C828. The format for the dot list, which is pointed to ;
; by the X register, is: ;
; ;
; ( rel y, rel x), (rel y, rel x), ..... ;
; ;
; The number of dots to draw is specified in $C823. ;
; ;
; ENTRY DP = $D0 ;
; X-reg points to the list of dot coordinates ;
; $C823 specifies the number of dots to draw ;
; ;
; EXIT: X-reg points to next byte after list ;
; $C823 cleared ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
LF2D2: DEC $C823 ;Decrement counter
Dot_List: BSR Dot_ix ;Draw next dot
LDA $C823 ;Check counter
BNE LF2D2 ;Go back until finished
BRA Reset0Ref ;Go to Reset0Ref
;-----------------------------------------------------------------------;
; F2DE Dot_List_Reset ;
; ;
; This routine draws a series of dots, specified by the list pointed ;
; to by the X register. The list has the following format: ;
; ;
; mode, relative y, relative x, ;
; mode, relative y, relative x, ;
; . . . ;
; . . . ;
; mode, relative y, relative x ;
; 0x01 ;
; ;
; This routine will continue to traverse the list, until a mode > 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
;-----------------------------------------------------------------------;
; F2FC Moveto_d_7F ;
; ;
; This routine forces the scale factor to 0x7F, and then moves the ;
; pen to the position specified in the D register. ;
; ;
; ENTRY DP = $D0 ;
; A-reg = relative Y coordinate ;
; B-reg = relative X coordinate ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Moveto_d_7F: STA
;-----------------------------------------------------------------------;
; F308 Moveto_ix_FF ;
; F30C Moveto_ix_7F ;
; F30E Moveto_ix_b ;
; ;
; These routines force the scale factor to 0xFF, 0X7F, or the ;
; A register, and then move the pen to the (y,x) position pointed to ;
; by the X-register. The X-register is then incremented by 2. ;
; ;
; ENTRY DP = $D0 ;
; X-reg points to the (y,x) coordinate pair ;
; B-reg contains the scale factor (Moveto_ix_b only) ;
; ;
; EXIT: X-reg has been incremented by 2 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Moveto_ix_FF: LDB #$FF
BRA Moveto_ix_b
Moveto_ix_7F: LDB #$7F
Moveto_ix_b: STB
;-----------------------------------------------------------------------;
; F310 Moveto_ix ;
; ;
; This routine uses the current scale factor, and moves the pen to the ;
; (y,x) position pointed to by the X register. The X register is then ;
; incremented by 2. ;
; ;
; ENTRY DP = $D0 ;
; X-reg points to the (y,x) coordinate pair ;
; ;
; EXIT: X-reg has been incremented by 2 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Moveto_ix: LDD ,X++
;-----------------------------------------------------------------------;
; F312 Moveto_d ;
; ;
; This routine uses the current scale factor, and moves the pen to the ;
; (y,x) position specified in D register. ;
; ;
; ENTRY DP = $D0 ;
; A-reg = Y coordinate ;
; B-reg = X coordinate ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Moveto_d: STA
;-----------------------------------------------------------------------;
; F34A Reset0Ref_D0 ;
; ;
; This routine sets the DP register to D0, and then resets the ;
; integrators. ;
; ;
; EXIT: DP = $D0 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Reset0Ref_D0: JSR DP_to_D0
BRA Reset0Ref
;-----------------------------------------------------------------------;
; F34F Check0Ref ;
; ;
; This routine will check to see if the Reset0Ref enable flag ($C824) ;
; is set, and if it is, then it will reset the integrators by calling ;
; Reset0Ref. ;
; ;
; ENTRY DP = $D0 ;
; $C824 = enable flag ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Check0Ref: LDA Vec_0Ref_Enable
BEQ LF36A_RTS
;-----------------------------------------------------------------------;
; F354 Reset0Ref ;
; ;
; This routine zeros the integrators, and resets the pen back to the ;
; origin. It leaves the integrators in zero mode, so nothing can be ;
; drawn until a move is done, or $D00C is set to 0xCE to bring /ZERO ;
; high. This routine must be called every so often, to prevent your ;
; vectors from getting out of whack. ;
; ;
; ENTRY DP = $D0 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Reset0Ref: LDD #$00CC
STB
;-----------------------------------------------------------------------;
; F35B Reset_Pen ;
; ;
; Reset the pen to the origin. ;
; ;
; ENTRY DP = $D0 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Reset_Pen: LDD #$0302
CLR
;-----------------------------------------------------------------------;
; F36B Reset0Int ;
; ;
; This routine resets the integrators to zero. It leaves the ;
; integrators in zero mode, so nothing can be drawn until a move is ;
; done, or D00C is set to 0xCE. ;
; ;
; ENTRY DP = $D0 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Reset0Int: LDD #$00CC
STB
;-----------------------------------------------------------------------;
; F373 Print_Str_hwyx ;
; ;
; This routine prints a single string (up to an 0x80). The parameter ;
; block describing the string is pointed to by the U register. The ;
; format for the parameter block is as follows: ;
; ;
; height, width, rel y, rel x, string, 0x80 ;
; ;
; ENTRY DP = $D0 ;
; U-reg points to the string list ;
; ;
; EXIT: U-reg points to the byte after the terminating 0x80 ;
; ;
; D-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
Print_Str_hwyx: LDD ,U++
STD Vec_Text_HW
;-----------------------------------------------------------------------;
; F378 Print_Str_yx ;
; ;
; This routine prints a single string (up to an 0x80), using the ;
; default height and width, as stored in $C82A. The parameter block ;
; describing the string is pointed to by the U register. The format ;
; for the parameter block is as follows: ;
; ;
; rel y, rel x, string, 0x80 ;
; ;
; ENTRY DP = $D0 ;
; U-reg points to the string list ;
; ;
; EXIT: U-reg points to the byte after the terminating 0x80 ;
; ;
; D-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
Print_Str_yx: LDD ,U++
;-----------------------------------------------------------------------;
; F37A Print_Str_d ;
; ;
; This routine prints a single string (up to an 0x80), using the ;
; default height and width, as stored in $C82A, and at the pen position ;
; specified in the D register. The parameter block describing the ;
; string is pointed to by the U register. The format for the ;
; parameter block is as follows: ;
; ;
; string, 0x80 ;
; ;
; ENTRY DP = $D0 ;
; U-reg points to string list ;
; A-reg = relative Y position ;
; B-reg = relative X position ;
; ;
; EXIT: U-reg points to the byte after the terminating 0x80 ;
; ;
; D-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
noopt ; neccessary for assembling, this jsr is allways
; optimized to a short branch otherwise
Print_Str_d: JSR >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
;-----------------------------------------------------------------------;
; F3B5 Mov_Draw_VLcs ;
; ;
; 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, and the scale factor is the second byte in the vector ;
; list. The vector list has the following format: ;
; ;
; count, scale, 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_VLcs: LDD ,X++
;-----------------------------------------------------------------------;
; F3B7 Mov_Draw_VL_ab ;
; F3B9 Mov_Draw_VL_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 vector list has the following format: ;
; ;
; rel y, rel x, rel y, rel x, ... ;
; ;
; ENTRY DP = $D0 ;
; A-reg = number of vectors to draw ;
; B-reg = scale factor to use (Draw_VL_ab only) ;
; X-reg points to the vector list ;
; ;
; EXIT: X-reg points to next byte after list ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Mov_Draw_VL_ab: STB
;-----------------------------------------------------------------------;
; F3BC Mov_Draw_VL ;
; F3BE Mov_Draw_VL_d ;
; ;
; 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, ... ;
; ;
; Draw_VL_d starts at the (y,x) coordinates specified in the D register ;
; and ignores the first pair of coordinates in the vector list. ;
; ;
; ENTRY DP = $D0 ;
; $C823 = number of vectors to draw ;
; D-reg = start coordinate (Draw_VL_d only) ;
; X-reg points to the vector list (2,X for Mov_Draw_VL_d) ;
; ;
; EXIT: $C823 is cleared ;
; ;
; EXIT: X-reg points to next byte after list ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Mov_Draw_VL: LDD ,X ;Get next coordinate pair
Mov_Draw_VL_d: STA 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
;-----------------------------------------------------------------------;
; F3D6 Draw_VLcs ;
; ;
; 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 scale factor is specified ;
; as the second byte in the vector list. The vector list has the ;
; following format: ;
; ;
; count, scale, 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_VLcs: LDD ,X++
;-----------------------------------------------------------------------;
; F3D8 Draw_VL_ab ;
; ;
; 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 ;
; A-reg = the number of vectors to draw ;
; 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_ab: STB
;-----------------------------------------------------------------------;
; F3DA Draw_VL_a ;
; ;
; This routine draws vectors between the set of (y,x) points pointed ;
; to by the register. The current scale factor is used. The vector ;
; list has the following format: ;
; ;
; rel y, rel x, rel y, rel x, ... ;
; ;
; ENTRY DP = $D0 ;
; A-reg = the number of vectors to draw ;
; X-reg points to the vector list ;
; ;
; EXIT: X-reg points to next byte after list ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Draw_VL_a: STA $C823
;-----------------------------------------------------------------------;
; F3DD Draw_VL ;
; ;
; This routine draws vectors between the set of (y,x) points pointed ;
; to by the X register. The number of vectors to draw must already be ;
; specified in $C823. The current scale factor is used. The vector ;
; list has the following format: ;
; ;
; 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_VL: LDD ,X
;-----------------------------------------------------------------------;
; F3DF Draw_Line_d ;
; ;
; This routine will draw a line from the current pen position, to the ;
; point specified by the (y,x) pair specified in the D register. The ;
; current scale factor is used. Before calling this routine, $C823 ;
; should be = 0, so that only the one vector will be drawn. ;
; ;
; ENTRY DP = $D0 ;
; A-reg = relative y position ;
; B-reg = relative x position ;
; ;
; EXIT: X-reg is incremented by 2 ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Draw_Line_d STA
;-----------------------------------------------------------------------;
; F404 Draw_VLp_FF ;
; F408 Draw_VLp_7F ;
; ;
; These routines force the scale factor to 0xFF or 0x7F, and then ;
; process the vector list pointed to by the X register. The vector ;
; list has the following format: ;
; ;
; pattern, rel y, rel x ;
; pattern, rel y, rel x ;
; . . . ;
; . . . ;
; pattern, rel y, rel x ;
; 0x01 ;
; ;
; The list is terminated by a pattern byte with the high bit cleared. ;
; ;
; ENTRY DP = $D0 ;
; X-reg points to the vector list ;
; ;
; EXIT: X-reg points to the terminator byte ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Draw_VLp_FF: LDB #$FF
BRA Draw_VLp_b
Draw_VLp_7F: LDB #$7F
BRA Draw_VLp_b
;-----------------------------------------------------------------------;
; F40C Draw_VLp_scale ;
; ;
; This routine processes the vector list pointed to by the X register. ;
; The first byte in the vector list is the scale factor. The vector ;
; list has the following format: ;
; ;
; scale ;
; pattern, rel y, rel x ;
; pattern, rel y, rel x ;
; . . . ;
; . . . ;
; pattern, rel y, rel x ;
; 0x01 ;
; ;
; The list is terminated by a pattern byte with the high bit cleared. ;
; ;
; ENTRY DP = $D0 ;
; X-reg points to the vector list ;
; ;
; EXIT: X-reg points to the terminator byte ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Draw_VLp_scale: LDB ,X+
;-----------------------------------------------------------------------;
; F40E Draw_VLp_b ;
; ;
; This routine draws patterned lines using the vector list pointed to ;
; by the X register. The vector list has the following format: ;
; ;
; pattern, rel y, rel x ;
; pattern, rel y, rel x ;
; . . . ;
; . . . ;
; pattern, rel y, rel x ;
; 0x01 ;
; ;
; The list is terminated by a pattern byte with the high bit cleared. ;
; ;
; ENTRY DP = $D0 ;
; B-reg = the scale factor ;
; X-reg points to the vector list ;
; ;
; EXIT: X-reg points to the terminator byte ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Draw_VLp_b: STB
;-----------------------------------------------------------------------;
; F410 Draw_VLp ;
; ;
; This routine draws patterned lines using the vector list pointed to ;
; by the X-register. The current scale factor is used. The vector ;
; list has the following format: ;
; ;
; pattern, rel y, rel x ;
; pattern, rel y, rel x ;
; . . . ;
; . . . ;
; pattern, rel y, rel x ;
; 0x01 ;
; ;
; The list is terminated by a pattern byte with the high bit cleared. ;
; ;
; ENTRY DP = $D0 ;
; X-reg points to the vector list ;
; ;
; EXIT: X-reg points to the terminator byte ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Draw_VLp: LDD 1,X ;Get next coordinate pair
STA
;-----------------------------------------------------------------------;
; F434 Draw_Pat_VL_a ;
; F437 Draw_Pat_VL ;
; F439 Draw_Pat_VL_d ;
; ;
; All of these routines draw a series of patterned vectors. The ;
; pattern to use must already be specified in $C829. When using ;
; Draw_Pat_VL or Draw_Pat_VL_d, the number of vectors to draw minus 1 ;
; must be specified in $C823; when using Draw_Pat_VL_a, the number of ;
; vectors to draw minus 1 must be passed in in the A register. ;
; The vector list, pointed to by the X register, has the following ;
; format: ;
; ;
; rel y, rel x, rel y, rel x, ... ;
; ;
; Draw_Pat_VL_d starts at the (y,x) coordinates specified in the ;
; D register and ignores the first pair of coordinates in the vector ;
; list. ;
; ;
; ENTRY DP = $D0 ;
; X-reg points to the vector list ;
; A-reg = the number of vectors to draw (Draw_Pat_VL_a only) ;
; D-reg = start (Y,X) coordinate (Draw_Pat_VL_d only) ;
; $C829 contains the line pattern. ;
; ;
; EXIT: X-reg points to next byte after list ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
LF433: DECA
Draw_Pat_VL_a: STA $C823
Draw_Pat_VL: LDD ,X ;Get next coordinate pair
Draw_Pat_VL_d: STA
;-----------------------------------------------------------------------;
; F46E Draw_VL_mode ;
; ;
; This routine processes the vector list pointed to by the X register. ;
; The current scale factor is used. The vector list has the following ;
; format: ;
; ;
; mode, rel y, rel x, ;
; mode, rel y, rel x, ;
; . . . ;
; . . . ;
; mode, rel y, rel x, ;
; 0x01 ;
; ;
; where mode has the following meaning: ;
; ;
; < 0 use the pattern in $C829 ;
; = 0 move to specified endpoint ;
; = 1 end of list, so return ;
; > 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
;-----------------------------------------------------------------------;
; F5D9 Get_Rise_Idx ;
; F5DB Get_Run_Idx ;
; ;
; These routines are responsible for generating the two index pairs ;
; which are required by the rest of the rotation routines. Each index ;
; pair is two bytes long, and has the following format: ;
; ;
; The high byte is obtained by masking the anglewith 0x1F (this ;
; forces the angle to be between 0 and 180 degrees), and then ;
; using this value to index into the multiplier table. ;
; ;
; The lower byte contains information about whether the angle ;
; lies along either the x or y axis, and whether the rise/run ;
; will be positive or negative. ;
; ;
; 0 => 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
;-----------------------------------------------------------------------;
; F5FF Rise_Run_X ;
; F601 Rise_Run_Y ;
; F603 Rise_Run_Len ;
; ;
; This routine takes an angle value which is relative to the x- or ;
; y-axis, and calculates the rise and run for that angle, relative to a ;
; passed-in scalar velocity value. A large scalar value will cause an ;
; object to move quickly, while a small scalar value will cause an ;
; object to move more slowly. ;
; ;
; Keep in mind that most games store x & y coordinates as 2 bytes each, ;
; with the upper byte being the actual coordinate, and the lower byte ;
; being that which is usually added to the rise/run value; when the ;
; lower byte overflows into the hi byte, then the object will 'move'. ;
; The rise/run values returned here are meant to be added to the low ;
; byte -- NOT the hi byte!! ;
; ;
; ENTRY DP = $C8 ;
; A-reg = the scalar velocity value (except Rise_Run_Len) ;
; B-reg = the Vectrex angle value ;
; ;
; EXIT: A-reg = the rise value ;
; B-reg = the run value ;
; ;
; All other registers are saved. ;
;-----------------------------------------------------------------------;
Rise_Run_X: SUBB #$10
Rise_Run_Y: STB
;-----------------------------------------------------------------------;
; F610 Rot_VL_ab ;
; F616 Rot_VL ;
; ;
; This routine rotates a vector list of length 'n+1', where 'n' is ;
; specified by the value in the B register. The A register contains ;
; the rotation value, and the X contains a pointer to the vector list. ;
; The U register contains a pointer to a buffer into which the ;
; transformed points are to be saved. The vector list has the ;
; following format: ;
; ;
; rel y, rel x, rel y, rel x, ... ;
; ;
; ENTRY A-reg = rotation angle value (Rot_VL_ab only) ;
; $C836 = rotation angle value (Rot_VL only) ;
; B-reg = number of points - 1 (Rot_VL_ab only) ;
; $C823 = number of points - 1 (Rot_VL only) ;
; X-reg points to original vector list ;
; U-reg points to rotated vector list ;
; ;
; EXIT: DP = $C8 ;
; X-reg points to next byte after list ;
; U-reg points to next byte after rotated list ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Rot_VL_ab: STA Vec_Angle
STB $C823
Rot_VL: PSHS DP
JSR DP_to_C8
BSR Rise_Run_Idx
BRA LF637
;-----------------------------------------------------------------------;
; F61F Rot_VL_Mode ;
; F62B Rot_VL_M_dft ;
; ;
; This routine rotates a vector list having the following format: ;
; ;
; mode, rel y, rel x, ;
; mode, rel y, rel x, ;
; . . . ;
; . . . ;
; mode, rel y, rel x, ;
; 0x01 ;
; ;
; The A register contains the rotation value, and the X contains a ;
; pointer to the vector list. The U register contains a pointer to a ;
; buffer into which the transformed points are to be saved. ;
; ;
; ENTRY DP = $C8 ;
; A-reg = rotation angle value (Rot_VL_Mode only) ;
; X-reg points to original vector list ;
; U-reg points to rotated vector list ;
; ;
; EXIT: X-reg points to next byte after list ;
; U-reg points to next byte after rotated list ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Rot_VL_Mode: STA Vec_Angle ;Save angle
PSHS DP ;Save DP register
JSR DP_to_C8 ;DP to RAM
STA <$C823 ;Store $C8 (negative value) into $C823
BSR Rise_Run_Idx ;Get index pair of angle
Rot_VL_M_dft: LDA ,X+ ;Get mode byte
STA ,U+ ;Copy to destination
BLE LF637 ;Rotate if not end of list
CLR <$C823 ;Exit with $C823 cleared
PULS DP,PC ;Restore DP register and return
LF635: DEC <$C823 ;Decrement count for (y,x) list
LF637: LDA ,X+ ;Get y coordinate
BSR Xform_Rise_a
STA ,U ;Store partial y coordinate
LDA ,X ;Get x coordinate
BSR Xform_Run_a
ADDA ,U ;Add to partial y coordinate
STA ,U+ ;Store rotated y coordinate
LDA -1,X ;Get y coordinate
BSR Xform_Run_a
STA ,U ;Store partial x coordinate
LDA ,X+ ;Get x coordinate
BSR Xform_Rise_a
SUBA ,U ;Add to partial x coordinate
STA ,U+ ;Store rotated x coordinate
LDA <$C823 ;Get counter
BMI Rot_VL_M_dft ;If negative, go back to mode list loop
BNE LF635 ;If non-zero, go back to (y,x) list loop
PULS DP,PC
;-----------------------------------------------------------------------;
; F65B Xform_Run_a ;
; F65D Xform_Run ;
; ;
; These two routines generate a run value, using the run index pair in ;
; $C837-$C838. For Xform_Run_a the scalar value is passed in the ;
; A register, while for Xform_Run, the scalar value must already be in ;
; $C83B. The transformed value is return in the A register. ;
; ;
; ENTRY DP = $C8 ;
; A-reg = length for rise/run (Xform_Rise_a only) ;
; ;
; EXIT: A-reg = run value ;
; ;
; B-reg trashed ;
;-----------------------------------------------------------------------;
Xform_Run_a: STA
;-----------------------------------------------------------------------;
; F67F Move_Mem_a_1 ;
; F683 Move_Mem_a ;
; ;
; This routine copies a block of memory, starting at the hi address, ;
; and working down to the low address. The base of the source address ;
; is specified in the U register, and the base of the destination ;
; address is specified in the X register. The A register contains ;
; the number of bytes to copy; 0x80 is the maximum value which can ;
; be specified. ;
; ;
; ENTRY A-reg = byte count (Move_Mem_a only) ;
; A-reg = byte count minus 1 (Move_Mem_a_1 only) ;
; X-reg points to the destination ;
; U-reg points to the source ;
; ;
; EXIT A-reg = $FF ;
; B-reg = first byte of source ;
;-----------------------------------------------------------------------;
Move_Mem_a_1: LDB A,U ;Copy the byte
STB A,X
Move_Mem_a: DECA ;Decrement the count
BPL Move_Mem_a_1 ;Go back until finished
LF686: RTS
;-----------------------------------------------------------------------;
; F687 Init_Music_chk ;
; F68D Init_Music ;
; F692 Init_Music_dft ;
; ;
; These routines are responsible for filling the music work buffer ;
; while a sound is being made. It should be called once during each ;
; refresh cycle. If you want to start a new sound, then you must set ;
; $C856 to 0x01, and point the U-register to the sound block. If no ;
; sound is in progress ($C856 = 0), then it returns immediately ;
; (unless you called Init_Music or Init_Music_dft, which do not make ;
; this check). When a sound is in progress, $C856 will be set to 0x80. ;
; ;
; These routines process a single note at a time, and calculate the ;
; amplitude and course/fine tuning values for the 3 sound channels. ;
; The values calculated are stored in the music work buffer, at ;
; $C83F-$C84C. ;
; ;
; Music data format: ;
; ;
; header word -> $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
;-----------------------------------------------------------------------;
; F835 Display_Option (not called by GCE cartridges) ;
; ;
; This routine displays the player or game option string, along with ;
; the current value for that option. The A-register contains the ;
; value of the option, while the Y-register points to a block of the ;
; following form: ;
; ;
; rel y, rel x, ( for value ) ;
; rel y, rel x, ( for option string) ;
; option string, ;
; 0x80 ;
; ;
; ENTRY DP = $D0 ;
; A-reg=the option value. ;
; Y-reg points to the string block. ;
; ;
; D-reg, U-reg, X-reg trashed ;
;-----------------------------------------------------------------------;
Display_Option: LDX #$C85E ;Point to temp storage
PSHS A ;Save option
BSR Clear_Score ;Clear scratch score accumulator
LDA ,S+ ;Get option back
BEQ LF84E ;Exit printing nothing if option = zero
BSR Add_Score_a ;Put option in scratch score accumulator
TFR X,U ;Transfer X to be printed
LDD ,Y++ ;Get (y,x) of value
JSR Print_Str_d ;Print value
TFR Y,U ;Transfer Y to be printed
JSR Print_Str_yx ;Print option string
LF84E: RTS
;-----------------------------------------------------------------------;
; F84F Clear_Score ;
; ;
; This routine will initialize the passed-in score string (pointed to ;
; by the X-register) to the following value: ;
; ;
; " 0",0x80 ;
; ;
; ENTRY X-reg points to seven byte score accumulator ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Clear_Score: LDD #' '*256+' ' ;Store the leading blanks
STD ,X
STD 2,X
STA 4,X
LDD #'0'*256+$80 ;Store the zero and terminator byte
STD 5,X
RTS
;-----------------------------------------------------------------------;
; F85E Add_Score_a ;
; F87C Add_Score_d ;
; ;
; These routines take the BCD value in the D-register or the binary ;
; value in the A-register, and add it to the 6-byte ASCII number ;
; pointed by the X-register. ;
; ;
; ENTRY A-reg = binary value (Add_Score_a only) ;
; D-reg = BCD value (Add_Score_d only) ;
; U-reg = BCD conversion of A-reg (Add_Score_a only) ;
; X-reg points to six byte ASCII score accumulator ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Add_Score_a: LDU #$0000 ;Initialize BCD result to zero
LF861: CMPA #99 ;Add in the hundreds
BLS LF86D
SUBA #100
LEAU $0100,U
BRA LF861
LF86D: CMPA #9 ;Add in the tens
BLS LF878
SUBA #10
LEAU $10,U
BRA LF86D
LF878: LEAU A,U ;Add in the ones
TFR U,D ;Move it to the D-register
Add_Score_d: PSHS A ;Save BCD on stack in reverse order
PSHS B
LDB #$05
LF882: CLRA ;Add zero to 10000 and 100000 digits
CMPB #$01
BLS LF897
BITB #$01 ;Add right nibble to hundreds and ones
BEQ LF88F
LDA ,S
BRA LF895
LF88F: LDA ,S+ ;Add left nibble to thousands and tens
LSRA
LSRA
LSRA
LSRA
LF895: ANDA #$0F ;Isolate desired nibble
LF897: ADDA $C823 ;Add in carry ($C823 is normally zero)
CLR $C823 ;Clear carry
ADDA B,X ;Add to digit
CMPA #'0'-1 ;If digit was a blank,
BGT LF8A5
ADDA #$10 ; promote the result to a digit
LF8A5: CMPA #'9' ;If a carry has occurred,
BLS LF8AE
SUBA #10 ; subtract ten
INC $C823 ; and set carry flag
LF8AE: STA B,X ;Store resulting digit
DECB ;Go back for more digits
BPL LF882
CLR $C823 ;Clear $C823 back to zero
CLRB
;-----------------------------------------------------------------------;
; F8B7 Strip_Zeros ;
; ;
; This routine strips the leading zeros from a score accumulator. ;
; ;
; ENTRY B-reg = first digit to start with (usually zero) ;
; X-reg points to six byte ASCII score accumulator ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Strip_Zeros: LDA B,X ;Test current digit
CMPA #'0'
BNE LF8C6 ;Exit if not zero
LDA #' ' ;Change it to a blank
STA B,X
INCB
CMPB #$05
BLT Strip_Zeros
LF8C6: RTS
;-----------------------------------------------------------------------;
; F8C7 Compare_Score ;
; ;
; This routine will compare two BCD score strings, to determine which ;
; one is higher. The two strings are pointed to by the U and X ;
; registers. Depending upon how the scores compare, one of the ;
; following values will be returned in the A-register: ;
; ;
; 1) The scores are the same: a = 0 ;
; 2) X score > 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
;-----------------------------------------------------------------------;
; FF9F Draw_Grid_VL ;
; ;
; This routine apparently will draw a vector list using a 16x16 grid, ;
; and occasionally using regular vector lists too. This could possibly ;
; be useful for drawing gridded things like a chess board and all of ;
; its pieces at the same time. ;
; ;
; The master vector list contains multiple sublists that start with ;
; a flag byte: ;
; Bit 7 = draw the next regular vector list (from X-reg) first ;
; Bit 6 = this is the last sublist in the master vector list ;
; Bits 5,4 = unused ;
; Bits 3-0 = number of points in this sublist (1-16) ;
; ;
; The points are stored as a pair of nibbles: ;
; Bits 7-4 = Y coordinate (?) ;
; Bits 3-0 = X coordinate (?) ;
; ;
; ENTRY DP = $D0 ;
; X-reg points to regular vector lists ;
; Y-reg points to master vector list ;
; ;
; EXIT: X-reg points to next byte after last regular vector list used ;
; Y-reg points to next byte after end of master vector list ;
; ;
; D-reg trashed ;
;-----------------------------------------------------------------------;
Draw_Grid_VL: LDA ,Y+ ;Get flag byte
BRA LFFAB ;Jump into loop
LFFA3: JSR Mov_Draw_VL_d ;Draw a regular vector list
LDA $C880 ;Clear vector list flag
ANDA #$7F
LFFAB: STA $C880 ;Save flag byte for vector count
LFFAE: DEC $C880 ;Decrement vector count
LDA ,Y ;Get Y of next point
ASRA
ANDA #$F8
LDB ,Y+ ;Get X of next point
ASLB
ASLB
ASLB
ASLB
ASRB
ANDB #$F8
TST $C880 ;Draw a regular vector list?
BMI LFFA3 ;Go back if so
JSR Draw_Line_d ;Draw a line to the new point
LDA $C880 ;Check vector counter
BITA #$0F
BNE LFFAE ;Go back if more vectors to draw
BITA #$20 ;Check for end of list
BEQ Draw_Grid_VL ;Go back if more lists to draw
RTS
FCC "KARRSOFT82LDMCBCJT82LDMCBCJ"
FDB 0,0 ;Unused
FDB $CBF2 ;SWI3 vector
FDB $CBF2 ;SWI2 vector
FDB $CBF5 ;FIRQ vector
FDB $CBF8 ;IRQ vector
FDB $CBFB ;SWI vector
FDB $CBFB ;NMI vector
FDB Start ;Reset vector
END Start