include "OSMap.h" include "MSMap.h" include "FnMap.h" ; ; This work was originally done by Fred Taft ; (fred@hp.com). Please forward any comments, ; corrections or additions back to Fred. ; ; Mine Storm ; ;******************************************** ; ; The following is the memory map for ; Minestorm RAM usage: ; ; C880 This contains the enable mask ; used when Minestorm wants to ; read the console buttons. ; ; C881-C882 This contains the mask used ; by Minestorm when it wants to ; read the joystick state. ; This mask will be used for ; both the console 1 & 2 pots; ; console 2 ones are ignored. ; ; C883 Used when calculating the ; angle at which a magnetic ; mine will travel, as it is ; drawn toward the command ; ship. It will end up holding ; the new angle value. ; ; C884-C886 Not used. ; ; C887-C888 Used when calculating the ; value of a mine; contains ; any bonus for the mine size. ; ; C889-C88A Used when calculating the ; value of a mine; contains the ; base value for the mine type; ; the mine size bonus is later ; added in. ; ; C88B Work variable. ; ; C88C-C88E Not used. ; ; C88F This is used as a loop ; counter during bullet ; processing. ; ; C890-C891 Work variables. ; ; C892-C89A Not used. ; ; C89B This indicates which players ; turn it is: ; ; 0 -> Player 1 ; 2 -> Player 2 ; ; C89C ; C89D-C89E These locations are used as ; an indirect jump pointer and ; counter pair. The address of ; the routine to be called is ; placed in C89D-C89E, and a ; value is placed in C89C. ; Each time through the main ; loop, the counter is ; decremented. When the value ; finally reaches 0, the ; routine will be called. By ; using random counters, you ; can make things behave ; differently each time. ; ; C89F ; C8A0-C8A1 These locations are used as ; an indirect jump pointer and ; counter pair. The address of ; the routine to be called is ; placed in C8A0-C8A1, and a ; value is placed in C89F. ; Each time through the main ; loop, the counter is ; decremented. When the value ; finally reaches 0, the ; routine will be called. By ; using random counters, you ; can make things behave ; differently each time. ; ; C8A2 ; C8A3-C8A4 These locations are used as ; an indirect jump pointer and ; counter pair. The address of ; the routine to be called is ; placed in C8A3-C8A4, and a ; value is placed in C8A2. ; Each time through the main ; loop, the counter is ; decremented. When the value ; finally reaches 0, the ; routine will be called. By ; using random counters, you ; can make things behave ; differently each time. ; ; C8A5 ; C8A6-C8A7 These locations are used as ; an indirect jump pointer and ; counter pair. The address of ; the routine to be called is ; placed in C8A6-C8A7, and a ; value is placed in C8A5. ; Each time through the main ; loop, the counter is ; decremented. When the value ; finally reaches 0, the ; routine will be called. By ; using random counters, you ; can make things behave ; differently each time. ; ; C8A8-C8AE This is a 7 byte buffer, used ; to contain player 1's score ; string. The string has the ; following format: ; ; " 0",0x80 ; ; C8AF-C8B5 This is a 7 byte buffer, used ; to contain player 2's score ; string. The string has the ; following format: ; ; " 0",0x80 ; ; C8B6 Flags that a bullet sound ; should be made. ; ; C8B7 Used as a loop counter during ; initial screen seeding. ; ; C8B8 Used as a temporary variable ; in several places. ; Saves number of mines, during ; screen re-seeding. ; ; C8B9-C8BA Points to an entry in the ; mine buffer; used during ; screen re-seeding. ; ; C8BB-C8BC Not used. ; ; C8BD Flags that the command ship ; has been disabled. ; ; C8BE Set when the active player ; has no more command ships to ; play with. ; ; C8BF During a screen re-seed ; operation (when the user has ; cleared all but small mines), ; this keeps track of the ; number of mines which still ; need to be re-seeded by the ; mother ship. ; ; C8C0 This flags that a new mine ; has been made visible, during ; screen re-seeding. ; ; C8C1 Used as a loop counter during ; mine re-seeding. ; ; C8C2-C8C3 This contains a pointer into ; the structure describing ; which mines are visible at ; the level the active player ; is at. ; ; C8C4-C8C5 This contains a pointer into ; the structure describing ; which mines are visible at ; the level that player 1 is ; at. ; ; C8C6-C8C7 This contains a pointer into ; the structure describing ; which mines are visible at ; the level that player 2 is ; at. ; ; C8C8-C8C9 This contains the y ; coordinate of the command ; ship. When drawing the ; command ship, only the upper ; byte (C8C8) is used. The ; lower byte is there only to ; make motion graceful; i.e. ; when the ship is moving, the ; motion delta is added into ; the lower byte (C8C9), and ; the ship will only end up ; moving, when the lower byte ; overflows into the upper ; byte. ; ; C8CA-C8CB This contains the x ; coordinate of the command ; ship. When drawing the ; command ship, only the upper ; byte (C8CA) is used. The ; lower byte is there only to ; make motion graceful; i.e. ; when the ship is moving, the ; motion delta is added into ; the lower byte (C8CB), and ; the ship will only end up ; moving, when the lower byte ; overflows into the upper ; byte. ; ; C8CC-C8CD ; C8CE-C8CF ; C8D0-C8D1 ; C8D2-C8D3 Used when calculating ship ; movement. ; ; C8D4 This contains the rotation ; value for the command ship. ; ; C8D5 This contains the velocity of ; the command ship. ; ; C8D6 ; C8D7 ; C8D8 These are used when ; calculating the x and y ; position for the command ; ship, while it is moving. ; ; C8D9 This contains the extra ship ; count for the active player. ; ; C8DA This contains the extra ship ; count for player 1. ; ; C8DB This contains the extra ship ; count for player 2. ; ; C8DC-C8DD Contains the position (y,x) ; at which the enemy mother ; ship is to be drawn. ; ; C8DE-C8DF Used to calculate the y ; coordinate of the enemy ; mother ship, during screen ; re-seeding. ; ; C8E0-C8E1 Used to calculate the x ; coordinate of the enemy ; mother ship, during screen ; re-seeding. ; ; C8E2-C8E3 Used to calculate the y ; coordinate of the enemy ; mother ship, during screen ; re-seeding. ; ; C8E4-C8E5 Used to calculate the x ; coordinate of the enemy ; mother ship, during screen ; re-seeding. ; ; C8E6 This contains the value which ; indicates at what angle a ; re-seeded mine will drift. ; ; C8E7 Flags that the enemy mother ; ship is out re-seeding the ; screen, because the user has ; cleared all but some small ; mines. ; ; C8E8-C8E9 Use as temporary storage for ; a pointer. ; ; C8EA This contains the number of ; active bullets. ; ; C8EB This is used to keep track of ; the number of active (those ; which are floating around) ; mines. ; ; C8EC This is set after the command ; ship has started exploding, ; and is cleared when the ; command ship explosion has ; completed. ; ; C8ED This contains the number of ; unused mines; i.e. those ; which are still dots. ; ; C8EE Flags that a hyperspace is ; active. ; ; C8EF This contains the scale ; factor to be used the next ; time the hyperspace dots are ; drawn. This value is ; decremented by 4 each time ; through the loop, until the ; lower limit is reached; at ; that point, the hyperspace is ; complete. ; ; C8F0-C8F1 This serves as the end of ; game loop counter; after a ; game is over, the system ; waits awhile (unless you ; press a button) before it ; starts a new game ; automatically. When this ; value decrements to 0, the ; new game starts. ; ; C8F2 Flags that the command ship ; movement sound should be ; made. ; ; C8F3 Flags that an explosion sound ; should be made. ; ; C8F4 Flags that a sound for a new ; mine 'popping' up should be ; made. ; ; C8F5 Not used. ; ; C8F6 Flags that the hyperspace ; sound should be made. ; ; C8F7 Used as a counter, while the ; command ship is being ; destroyed. ; ; C8F8 Contains the scale factor ; which is used to draw the ; command ship, as it is being ; destroyed. This is ; incremented, to give the ; effect of the ship being ; destroyed, and the parts ; separating. ; ; C8F9-C8FF This is a 7 byte buffer, used ; to contain player 1's level ; string. The string has the ; following format: ; ; " 0",0x80 ; ; C900-C906 This is a 7 byte buffer, used ; to contain player 2's level ; string. The string has the ; following format: ; ; " 0",0x80 ; ; C907-C908 ; C909-C90A These are used to contain ; some calculated values, which ; are used to transform the ; command ships coordinates. ; These values pertain to ; rotation, and could possibly ; be sin & cos values. ; Actually, I think they are ; rise & run values. ; ; C90B-C932 This is a 40 byte buffer, ; used to keep track of active ; bullets. The buffer is ; composed of 4 entries, each ; of 10 bytes. Upto 4 bullets ; may be active at any moment. ; See the section on Data ; Structures, for an ; explanation of how this ; buffer is organized. ; ; C933-CB2A This is a 504 byte buffer, ; used to keep track of all of ; the mines (both active, ; inactive & dead). The buffer ; is composed of 28 entries, ; each of 18 bytes. See the ; section on Data Structures, ; for an explanation of how ; this buffer is organized. ; ; CB2B-CB70 This is a 70 byte buffer, ; used to keep track of ; explosions which are ; currently being displayed. ; The buffer is composed of 14 ; entries, each of 5 bytes. ; Obviously, only upto 14 ; explosions can be displayed ; at any one time. See the ; section on Data Structures, ; for an explanation of how ; this buffer is organized. ; ; CB71-CB80 This is an array of 8 ; pointers. Each of these ; pointers point to a set of ; motion dots, which are drawn ; as the ship (and user) move ; to the next mine level. They ; are meant to simulate ship ; motion. ; ; CB81-CB88 This is an array of 8 scale ; factors. The scale factors ; are used when the ; corresponding set of motion ; dots (see above entry) are ; drawn. ; ; CB89-CBA2 This is a 26 byte buffer, ; used to hold the ; transformated points which ; make up the command ship. ; The values here are produced ; by taking the command ship ; points, and running them ; through a rotation ; transformation. ; ; CBA3-CBA6 Not used. ; ; CBA7-CBB3 This is a 13 byte buffer, ; used to hold the ; transformated points which ; make up a fire ball. These ; are re-transformed every so ; often, to give the fireball ; the effect of rotating. ; ;********* ; ; DATA STRUCTURES ; --------------- ; ; Bullet Structure ; ; Each entry in the bullet structure is ; composed of 10 bytes. The format for ; an entry is as follows: ; ; ------------------- 0 = not in use ; 0 | in-use flag | 1 = in use ; ------------------- ; 1 | Rise | ; - - ; 2 | Value | ; ------------------- ; 3 | Run | ; - - ; 4 | Value | ; ------------------- ; 5 | Bullet y | ; - - ; 6 | Coordinate | ; ------------------- ; 7 | Bullet x | ; - - ; 8 | Coordinate | ; ------------------- Time until ; 9 | Life span | bullet dies ; ------------------- (disappears) ; ; ; ; Mine Structure ; ; Each entry in the mine structure is ; 18 bytes, and has the following ; format: ; ; ; ------------------- ; 0 | State flag | (see note 1) ; ------------------- ; 1 | Mine type | (see note 2) ; ------------------- ; 2 | Scale Factor | ; ------------------- ; 3 | Generation # | (see note 3) ; ------------------- ; 4 | Mine y | ; - - ; 5 | Coordinate | ; ------------------- ; 6 | Mine x | ; - - ; 7 | Coordinate | ; ------------------- ; 8 | Rise | ; - - ; 9 | Value | ; ------------------- ; 10 | Run | ; - - ; 11 | Value | ; ------------------- ; 12 | Width of mine/2 | ; ------------------- ; 13 | Height of mine/2| ; ------------------- ; 14 | Value of | ; - - ; 15 | Mine (BCD) | ; ------------------- ; 16 | (see note 4) | ; ------------------- ; 17 | final x postion | ; ------------------- ; ; note1 : The state flag is used to ; indicate what the state of ; this mine is. It can take on ; one of the following values: ; ; 0x00 No mine defined. ; 0x01 Being destroyed. ; 0x08 Visible, and moving. ; 0x10 Visible, not moving. ; 0x20 Becoming visible. ; 0x40 Mine is still a dot. ; 0x80 Dot is still moving ; to its final x ; position. ; ; The life of a mine follows the story ; presented below. Before a mine is ; defined, the state is 0x00. When a ; mine is first being seeded, a final x ; position is calculated, and the mine ; is 'dropped' from the mother ship; ; the state is now 0x80. It will drift ; off in the x direction, until it ; reaches its final x position; the ; state is now 0x40. As the mine is ; first made visble, the state will ; become 0x20. Once a mine is visible, ; it does not immediately start moving; ; the state is now 0x10. Once the mine ; starts moving, the state becomes ; 0x08. When (if) the mine is ever ; destroyed, the state will be 0x01 ; while the explosion pattern is ; displayed. When the explosion ; pattern is complete, the state will ; revert back to 0x00. ; ; note2 : The mine type can take on any ; of the following 5 values: ; ; 0 dumb mine ; 1 magnetic mine ; 2 fireball mine ; 3 magnetic fireball ; 4 fireball ; ; note3 : The generation number ; indicates whether the mine is ; a large (3), medium (2) or ; small (1) mine. ; ; note4 : Depending upon the state of ; the mine, this field can mean ; 1 of 3 things: ; ; 1) When the mine is a dot, ; moving towards its final ; resting place, this ; contains the delta x ; value; i.e. how much it ; should move each time, ; until it reaches its final ; resting place. ; ; 2) If this is a large mine, ; then when the mine first ; 'pops' up, it doesn't go ; right from a dot to a ; large mine; rather, it ; goes from a dot to a small ; mine, to a medium mine, ; and then to a large mine. ; It this case, this field ; contains the scale factor ; which is used to draw the ; large mine as it 'pops' ; up. ; ; 3) Once a mine becomes ; visible, it does not ; immediately begin to move; ; it stays stationary for a ; short amount of time. In ; this case, this field ; contains a counter value, ; which says how long the ; mine should remain ; stationary. ; ; ; Explosion Buffer ; ; Each entry in the explosion buffer is ; 5 bytes long, and has the following ; format: ; ; ----------------------- ; 0 | Type of explosion |(see note 5) ; ----------------------- ; 1 | Max scale factor | ; ----------------------- ; 2 | Y coordinate | ; ----------------------- ; 3 | X coordinate | ; ----------------------- ; 4 |Current scale factor | ; ----------------------- ; ; note5: The type field can assume any ; of the following values: ; ; 0 = Not an active explosion ; 0x81 = Command ship explosion. ; all other = Mine/enemy ship explosion ; ;******************************************** ; org 0x0000; MS_header: db "g GCE 1988",0x80 dw MS_music ; Music block ptr db -8 ; height db 80 ; width db 48 ; rel y db -24 ; rel x db "MINE",0x80 db -8 ; height db 80 ; width db 0 ; rel y db -34 ; rel x db "STORM",0x80 db -8 ; height db 80 ; width db -48 ; rel y db -20 ; rel x db "III",0x80 db 0x00 ; Start of the Mine Storm game MS_start: ldx #ETMP1 ; Clear C883 - CBC5 PE019: clr ,x+ cmpx #ENDRAM bne PE019 jsr init_motion_dots inc ZSKIP lda #0xBB ; Set console enable sta SATUS ; flags ldx #0x0101 stx SJOY ; Set jstick mask restart_game: ldx #ETMP1 ; Clear C883 - CB70 PE034: clr ,x+ cmpx #MS_END bne PE034 bra PE03D direct $C8 PE03D: jsr DPRAM ldd #0x0200 ; Get # of players jsr SELOPT dec PLAYRS ; # players selected clr TSTAT clr ACTPLY ; Active player ldx #SCOR1 ; Init player 1 jsr SCLR ; score ldx #SCOR2 ; Init player 2 jsr SCLR ; score ldx #P1LVL ; Init mine field # jsr SCLR ; for player 1 ldd #0x0001 jsr SCRADD ldx #P2LVL ; Init mine field # jsr SCLR ; for player 2 ldd #0x0001 jsr SCRADD ldx #mines_at_level_x ; Init ptrs stx P1MINES ; describing mines stx P2MINES ; at current level. lda #0x05 ; # ships for active sta CPXSHP ; player sta P1XSHP ; Player 1 ships sta P2XSHP ; Player 2 ships bra restart_same_level start_next_mine_level: jsr bring_ship_to_center ldy #P1MINES ; Point to mine info lda ACTPLY ; for the next level ldx a,y leax 4,x stx a,y ldx #mine_field_level_pointers lda ACTPLY ; Award bonus ship ldx a,x ; if level is a lda 5,x ; multiple of 4 anda #0x03 bne goto_next_mine_level inc CPXSHP goto_next_mine_level: ldd #0x0001 ; Incr mine field jsr SCRADD ; level indicator. restart_same_level: jsr init_RAM_for_new_level ldx #P1MINES ; Use active players lda ACTPLY ; info to determine ldx a,x ; mines at this lda ,x ; level. bmi check_4_end_of_game ; After level jsr seed_the_screen ; 13, skip any bra main_loop ; level whose 1st ; byte is negative. check_4_end_of_game: ldd ENDCNTR ; If ENDCNTR counts subd #0x0001 ; down to 0, start a std ENDCNTR ; a new game. beq start_a_new_game ; Display 'game over' string, & both ; scores pshs dp jsr DPIO direct $D0 jsr display_both_scores ldu #game_over jsr MS_print_1_string7F puls dp direct $C8 lda TRIGGR ; If no buttons beq main_loop ; pressed, then see ; if we should goto ; advanced levels. ; Find out if a new hi score is ; available, and then start up a new ; game. start_a_new_game: ldx #SCOR1 ; Check player 1 ldu #HISCOR ; score. jsr HISCR ldx #SCOR2 ; Check player 2 ldu #HISCOR ; score. jsr HISCR ldd ENDCNTR lbne restart_game ; Start new game jsr INTALL clr LEG ; Flag that hi score lds #STKSTRT ; should be shown. jmp PWRUP ; Go thru complete ; reset sequence . ; ; This is the main loop during a players ; turn. Control will remain in this loop, ; until either a player clears a level, ; or has his ship destroyed. main_loop: pshs dp jsr process_indirect_jumps jsr draw_non_dead_mines jsr process_jstick_and_buttons jsr process_bullets jsr reseed_screen puls dp jsr check_bullets_for_hits jsr check_ship_4_mine_collision jsr check_ship_4_enemy_collision jsr display_explosion_pattern blo main_loop lda CS_DIS ; See if cmd ship is lbeq start_next_mine_level ; disabled. lda GAMEOVR ; See if the game is lbne check_4_end_of_game ; over. jmp restart_same_level ; ; This block of code is responsible for ; seeding the screen at the beginning of ; play. It will draw the enemy ship as it ; moves from the top of the screen to the ; bottom. After the field has been ; completely seeded, the mine field number ; will be displayed. I think that the x ; register, at entry, points to a structure ; describing the types of mines for this ; level. seed_the_screen: stx CPMINES ; Save mine info ptr ldd #0x7F00 std MSHP_YX ; Enemy ship coords . sta SEEDCTR ; Loop cntr (0x7F) . lda #0x20 sta TMR1 ; Set indirect jump ldx #generate_mine_coords ; ptr to stx T1FUNC ; set mine coords. ldx #MINEBUF ; Load mine buf addr stx MINEPTR lda #0x1D ; Load # of mines sta MINECNT clr TSTAT ldu #MS_music jsr SPLAY continue_seeding_screen: pshs dp ; Draw active player jsr PE711 ; ship count. jsr REPLAY lda FRAMLO ; Decr loop counter bita #0x01 ; every other pass. bne PE15C dec SEEDCTR PE15C: jsr process_indirect_jumps ; This block draws the enemy ship direct -1 jsr display_both_scores jsr REQOUT jsr draw_non_dead_mines jsr INT3Q ; Wait til screen is ldb SEEDCTR ; seeded, then start beq activate_4_mines ; 1st 4 mines. ldx #enemy_ship_pt1 ldy MSHP_YX jsr move_y_draw_x ; Draw enemy ship. ldx #enemy_ship_pt2 jsr move_y_draw_x ldx #enemy_ship_pt3 jsr move_y_draw_x puls dp direct $C8 ; Move enemy ship dec MSHP_Y ; from top to bottom bra continue_seeding_screen ; ; This routine is called at the beginning of ; a turn for the active player. It will ; activate the first 4 mines for the level. ; The type of mines activated are controlled ; by the array whose pointer is contained in ; CPMINES. activate_4_mines: puls dp clr TMR1 lda #0x04 ; Set loop counter. sta SEEDCTR ; Set delay counter; lda #0x7F ; when = 0, stop sta MINECNT ; displaying mine ; field # and start ; 1st 4 mines. PE198: lda SEEDCTR ; Exit when loop beq PE1E6 ; counter = 0 . ldb MINECNT beq PE1A4 ; Don't activate the dec MINECNT ; mines til MINECNT bra PE1B6 ; =0 to allow the ; mine field # to ; show a while. PE1A4: ldb FRAMLO ; After every 31 andb #0x1F ; loops, activate bne PE1B6 ; another mine. deca sta SEEDCTR ; Decr loop counter. ldx CPMINES lda a,x ; Get mine type. ldb #0x03 ; Set generation # jsr activate_a_mine ; to 'largest'. direct -1 PE1B6: pshs dp jsr process_indirect_jumps ; Tell user what mine field # this is jsr INTMAX ldu #mine_field jsr MS_print_1_string7F ldy #0xE0F8 ldu #mine_field_level_pointers lda ACTPLY ldu a,u jsr move_y_print_string jsr draw_non_dead_mines jsr process_jstick_and_buttons jsr process_bullets puls dp jsr check_bullets_for_hits jsr display_explosion_pattern bra PE198 PE1E6: rts ; ; This block of code generates random ; coordinates for a single mine. MINEPTR ; contains a pointer to the appropriate entry ; in the mine structure. Before exiting, ; this routine will update the pointer in ; MINEPTR to point to the next entry. direct $C8 generate_mine_coords: dec MINECNT ; Decr mine cntr. beq PE239 ; Exit when = 0. inc DOTMINE ; Incr mine dot cntr jsr RANDOM anda #0x07 ; Reset jump cntr to adda #0x04 ; generate next set sta TMR1 ; of mine coords. ldu MINEPTR ; Flag a mine is in lda #0x80 ; this slot . sta ,u ; Get the coords of ldd MSHP_YX ; the enemy ship. adda #0x08 sta 4,u ; Save y coord. clr 5,u stb 6,u ; Save x coord. clr 7,u generate_final_x_for_mine: jsr RANDOM ; Generate final x tsta ; pos for the mine. bmi PE21A cmpa #0x10 bge PE214 adda #0x0C PE214: cmpa #0x60 ble PE226 bra generate_final_x_for_mine PE21A: cmpa #0xF0 ble PE220 suba #0x0C PE220: cmpa #0xA0 bge PE226 bra generate_final_x_for_mine PE226: sta 0x11,u tfr a,b ; Determine delta sex ; movement value for ora #0x01 ; the mine (1 or -1) sta 0x10,u clr 2,u ; Set scale factor. leay 0x12,u ; Point to next slot sty MINEPTR PE239: rts final_mine_scale_factor: db 0x00 db 0x02 ; Small db 0x07 ; Medium db 0x10 ; Large mine_velocity: db 0x00 db 0x20 ; Small db 0x18 ; Medium db 0x10 ; Large mine_values: db 0x01 ; dumb mine = db 0x00 ; BCD 100. db 0x05 ; magnetic mine = db 0x00 ; BCD 500. db 0x03 ; fireball mine = db 0x25 ; BCD 325. db 0x07 ; magnetic fireball db 0x50 ; mine = BCD 750. extra_mine_value: db 0x00 db 0x00 db 0x01 ; Small (100) db 0x00 db 0x00 ; Medium (35) db 0x35 db 0x00 ; Large (0) db 0x00 mine_sizes: db 0x00 db 0x00 db 0x04 ; Small db 0x04 db 0x08 ; Medium db 0x08 db 0x0D ; Large db 0x0D ; Table of pointers to mine vectors mine_vector_ptrs: dw dumb_mine dw magnetic_mine dw fireball_mine dw magnetic_fireball_mine ; ; This block of code processes the hyperspace ; and move buttons. It also checks the state ; of the joystick, and updates the command ; ship rotation value, kept in SHPANGL, if ; the joystick is not centered. If the ; joystick is left, then the rotation value ; is incremented; if it is to the right, then ; the rotation value is decremented. After ; updating the rotation value, the command ; ship will be redrawn at its current ; position (specified in SHIP_Y - SHIPY+1). process_jstick_and_buttons: pshs dp lda #0xC8 tfr a,dp lda CS_DIS ; Skip if cmd ship lbne PE30A ; is disabled. lda HYPERON ; Continue hyperspace lbne continue_hyperspace ; if active. lda KEY1 ; Check hyperspace lbne hyperspace ; button (btn 2). lda KEY2 ; Check move button beq no_ship_movement ; (btn 3). ; ; The following block of code takes ; care of generating the new command ; coordinates, because it is moving. ; It attempts to make all turns into ; smooth motion. lda SHPANGL cmpa SHPANG2 beq PE2A0 cmpa SHPANG3 beq PE290 lda SHPVEL beq PE2A0 lda SHPANG4 bne no_ship_movement PE290: lda SHPANG4 adda #0x0C cmpa #0x7F bhi no_ship_movement sta SHPANG4 lda SHPANGL sta SHPANG3 bra PE2AE PE2A0: lda SHPVEL adda #0x0C cmpa #0x7F bhi no_ship_movement sta SHPVEL lda SHPANGL sta SHPANG2 PE2AE: inc MKMVSND ; Flag that a sound ; should be made . no_ship_movement: lda SHPVEL beq PE2C2 suba #0x02 sta SHPVEL ldb SHPANG2 jsr calc_rise_run1 sty SHIP_RISE_MOVING stx SHIP_RUN_MOVING PE2C2: lda SHPANG4 beq PE2D4 suba #0x02 sta SHPANG4 ldb SHPANG3 ; Calc new rise/run. jsr calc_rise_run1 sty SHPRIS2 stx SHPRUN2 PE2D4: ldd SHIP_Y ; Update cmd ships y addd SHIP_RISE_MOVING ; coord. addd SHPRIS2 std SHIP_Y ldd SHIP_X ; Update cmd ships x addd SHIP_RUN_MOVING ; coord. addd SHPRUN2 std SHIP_X ; Check joystick state (in POT0) lda POT0 beq draw_cmd_ship1; ; Centered. bmi PE2EE dec SHPANGL ; Joystick to right. bra draw_cmd_ship2 PE2EE: inc SHPANGL ; Joystick to left. bra draw_cmd_ship2 PE2F2: pshs dp ; ; draw_cmd_ship2() runs the command ships ; coordinates thru a rotation transformation, ; and then draws the command ship using the ; transformed coordinates. draw_cmd_ship1() ; draws the command ship using the current ; transformed ship coordinates. draw_cmd_ship2: jsr rotate_cmd_ship ; Rotate the cmd draw_cmd_ship1: ; ship. lda #0xD0 tfr a,dp direct $D0 jsr INT3Q ldb #0x0C ldy #SHIP_YX ; Draw xformed cmd ldx #XFRMSHP ; ship. jsr move_y_draw_x2 PE30A: puls dp,pc ; This routine handles the hyperspace request direct $C8 hyperspace: lda #0x80 sta HYPERON jsr RANDOM anda #0x03 adda #0x03 sta HYPSCAL inc MKHYSND continue_hyperspace: lda HYPERON bpl process_hyperspace_dots dec HYPSCAL beq PE330 jsr MS_get_2_random_nums sta SHIP_Y clr SHIP_YL ; Generate new cmd stb SHIP_X ; ship coords. clr SHIP_XL puls dp,pc PE330: lsr HYPERON lda #0x1F sta HYPSCAL puls dp,pc ; ; This code draws the ever decreasing ; hyperspace dots during an active ; hyperspace. The scale factor for the ; hyperspace dots, stored in HYPSCAL, is ; decremented, and when it finally reaches a ; minimum value, the hyperspace is complete. process_hyperspace_dots: ldb HYPSCAL ; See if scale cmpb #0xE0 ; factor has reached ble hyperspace_complete ; the limit. lda HYPSCAL suba #0x04 ; Decr scale factor. sta HYPSCAL clra jsr draw_hyperspace_motion_dots puls dp,pc hyperspace_complete: clr HYPSCAL clr HYPERON jsr clear_cmd_ship_xformation puls dp,pc ; ; After the player has cleared all but the ; small mines from a layer, the enemy ship ; will again appear, and attempt to reseed ; the screen. This code checks to see if ; the enemy ship is visible (RESEED), and if ; it is, then it generates new coordinates ; for it, and then moves it. direct -1 reseed_screen: lda RESEED ; do only if ship beq PE383 ; is visible . pshs dp lda #0xC8 tfr a,dp direct $C8 lda RESEED beq PE383 ldd NXMINEY addd MINERIS std NXMINEY sta MSHP_Y ; New y coord. ldd NXMINEX addd MINERUN std NXMINEX sta MSHP_X ; New x coord. puls dp direct -1 jsr INT3Q ldb #0x08 ldy MSHP_YX ldx #simple_enemy_ship jsr move_y_draw_x ; Draw enemy ship. PE383: rts ; ; This procedure is invoked only through the ; indirect jump pointers. After only small ; mines are left, this routine will ; eventually be called. It will determine ; which way the enemy ship will move, and ; will also set up another indirect jump to ; the routine which does the actual reseeding ; of the screen. direct $C8 ind_init_screen_reseeding: ldx #ind_reseed_screen stx T3FUNC ; Set up jump ptr. jsr RANDOM ldx #SE448 ; Determine where anda #0x06 ; enemy ship will ldx a,x ; move. ldd ,x++ std MSHP_YX ; Save enemy ships sta NXMINEY ; new coords. clr NXMINEY+1 stb NXMINEX clr NXMINEX+1 bra PE3F9 ; ; This routine is invoked only through the ; indirect jump mechanism. It will continue ; to be called, until either the enemy ship ; is destroyed, or until the screen has been ; reseeded. It will reseed upto 7 new mines. ind_reseed_screen: lda RESEDCT ; See if all mines bne PE3BE ; have been seeded. PE3A5: jsr RANDOM anda #0x7F adda #0x30 ; Set jump cntr for sta TMR3 ; the next pass. jsr RANDOM anda #0x3F sta RESDANG jsr RANDOM adda #0x10 sta RESEED bra PE407 PE3BE: lda CS_DIS bne PE3A5 ; ; Load the b register with the number ; of mines (28), and load the u ; register with the pointer to the mine ; structure. Then look through the ; mine structure for an available slot, ; and fill it with the newly seeded ; mine. ldb #0x1C ldu #MINEBUF PE3C7: lda ,u ; Find unused slot. beq found_avail_mine leau 0x12,u decb bne PE3C7 bra PE407 found_avail_mine: ; Incr # of mines inc DOTMINE ; which are dots. dec RESEDCT ; Decr reseed cntr. ldx NXMINEY stx 4,u ; Set mines y coord. ldx NXMINEX stx 6,u ; Set mines x coord. lda #0x40 ; Mine is a sta ,u ; stationary dot. lda NWMNVIS ; Check if 1st mine bne PE3F7 ; activated. ldx #ind_start_large_mine stx T1FUNC ; Set things up to jsr RANDOM ; eventually activate anda #0x7F ; 1 large mine. adda #0x40 sta TMR1 inc NWMNVIS ; Flag that 1st mine ; has been activated. PE3F7: ldx TMPPTR PE3F9: lda ,x+ sta TMR3 lda ,x+ sta RESDANG lda ,x+ sta RESEED stx TMPPTR PE407: ldb RESDANG jsr calc_rise_run1 ; Generate rise & sty MINERIS ; run for mine. stx MINERUN rts ; ; This routine is called only thru the ; indirect jump handler. It is responsible ; for activating a single large mine. The ; type of mine is indicated by the first ; entry in the table of mines for this level. ind_start_large_mine: ldu #P1MINES lda ACTPLY ldu a,u lda ,u ; Determine mine type ldb #0x03 ; Set generation to jsr activate_a_mine ; 'largest'. ldx #ind_activate_rangen_mine stx T1FUNC rts ; ; This routine decrements the counter in ; LOOPCTR, and if it equal 0, then it ; activates a mine with a random generation ; number; else, it sets the indirect counter ; in C89C to -1, and returns. This routine ; is called only thru the indirect jump ; handler. ind_activate_rangen_mine: dec LOOPCTR beq PE430 lda #0xFF sta TMR1 bra PE447 PE430: jsr RANDOM tfr a,b andb #0x03 bne PE43B addb #0x01 PE43B: ldu #P1MINES lda ACTPLY ldu a,u lda ,u jsr activate_a_mine PE447: rts ; Some sort of pointer table SE448: dw SE450 dw SE46A dw SE484 dw SE49E SE450: db 0x7F db 0x00 db 0x28 db 0x20 db 0x30 db 0x40 db 0x28 db 0x30 db 0x28 db 0x00 db 0x10 db 0x30 db 0x10 db 0x40 db 0x18 db 0x20 db 0x50 db 0x40 db 0x30 db 0x28 db 0x30 db 0x08 db 0x60 db 0x7F db 0x38 db 0x70 SE46A: db 0x80 db 0x00 db 0x40 db 0x00 db 0x30 db 0x20 db 0x10 db 0x50 db 0x20 db 0x28 db 0x40 db 0x30 db 0x3E db 0x70 db 0x18 db 0x30 db 0x60 db 0x20 db 0x18 db 0x40 db 0x30 db 0x24 db 0x50 db 0x7F db 0x06 db 0x70 SE484: db 0x00 db 0x7F db 0x40 db 0x10 db 0x60 db 0x28 db 0x38 db 0x30 db 0x28 db 0x08 db 0x40 db 0x30 db 0x28 db 0x7F db 0x20 db 0x18 db 0x30 db 0x30 db 0x08 db 0x68 db 0x40 db 0x20 db 0x50 db 0x7F db 0x38 db 0x70 SE49E: db 0x00 db 0x80 db 0x40 db 0x30 db 0x60 db 0x38 db 0x18 db 0x30 db 0x30 db 0x20 db 0x18 db 0x20 db 0x38 db 0x40 db 0x28 db 0x10 db 0x60 db 0x20 db 0x00 db 0x30 db 0x40 db 0x38 db 0x50 db 0x7F db 0x1C db 0x70 ; ; This routine is responsible for displaying ; any active bullets, and also for firing new ; bullets, when an available spot in the ; bullet structure becomes available. The ; maximum number of active bullets is 4. The ; 40 byte bullet structure starts at ; ACTIVE_BULLETS. A bullet will remain ; 'active' for at most 0x18 passes thru this ; routine. direct -1 process_bullets: lda #0x04 ; Loop counter = 4. ldu #ACTIVE_BULLETS ; Bullet buffer. ldx #KEY3 ; State of fire btn. sta TEMP1 jsr INTMAX next_bullet: ; If current slot is lda ,u ; empty, see if new beq check_fire_button; bullet should ; be fired. dec 9,u ; Decr cycle cntr and beq erase_bullet; erase bullet if = 0 ldd 5,u addd 1,u ; y std 5,u ; Incr bullet coords. ldd 7,u addd 3,u ; x std 7,u leay 5,u jsr draw_dot7F_ptr_in_y; Draw bullet. update_bufr_ptr: leau 10,u dec TEMP1 ; Point to next entry bne next_bullet rts erase_bullet: clr ,u dec NMACTBL ; Decr active bullet ; counter. check_fire_button: lda CS_DIS bne update_bufr_ptr lda HYPERON bne update_bufr_ptr lda ,x ; Check 'fire' btn. beq update_bufr_ptr ; ; This code 'fires' a new bullet, and ; fills the available spot in the ; bullet structure. clr ,x inc MKBLSND ; Flag that a bullet ; sound should be ; made. inc ,u ldd SHIP_Y ; Get ships coords. std 5,u ldd SHIP_X std 7,u ldd TRUE_SHIP_RISE ; Get ship rise. std 1,u ldd TRUE_SHIP_RUN ; Get ship run. std 3,u lda #0x18 ; # of passes before sta 9,u ; bullet expires. inc NMACTBL ; Incr active bullet bra update_bufr_ptr; counter. ; ; This procedure processes each mine which ; has not been destroyed. If the mine is a ; moving dot, then its position is updated; ; if the mine is a dot, then it is draw in ; its appropriate place; if the mine is ; active, then the appropriate mine is drawn; ; if it is a fireball, then the fireball is ; drawn. The state of the mine is determined ; by the first byte in the mine structure. ; The following values are valid: ; ; 0x00 - Mine is dead. ; 0x01 - Mine is being destroyed. ; 0x08 - Mine is visible and moving. ; 0x10 - Mine is visible, but not moving. ; 0x20 - Mine is just becoming visible. ; 0x40 - Mine is a stationary dot. ; 0x80 - Mine still moving to final resting ; place. ; draw_non_dead_mines: lda #0x1C sta TEMP1 ; Set loop cntr. ldu #MINEBUF ; Get mine ptr. PE526: lda ,u bne non_dead_mine update_mine_ptr: leau 0x12,u dec TEMP1 bne PE526 rts non_dead_mine: lbmi move_mine_dot bita #0x40 lbne draw_mine_as_dot bita #0x20 lbne mine_becoming_visible bita #0x10 lbne delay_B4_moving_mine bita #0x01 lbne process_destroyed_mine lda 1,u cmpa #0x04 ; Check for fireball. beq process_fireball bita #0x01 ; Move visible mines. beq non_magnetic_mine lda HYPERON ; Skip if hyperspace ; active. bne non_magnetic_mine lda CS_DIS ; Skip if cmd ship ; disabled. bne non_magnetic_mine pshs dp jsr DPRAM direct $C8 lda SHIP_Y ; Draw the mine suba 4,u ; towards the cmd ldb SHIP_X ; ship. subb 6,u jsr CMPASS suba #0x10 sta ETMP1 ldx #mine_velocity ldb 3,u lda b,x ldb ETMP1 jsr calc_rise_run1; Calc new rise and sty 8,u ; run values. stx 10,u puls dp direct -1 non_magnetic_mine: ldd 4,u ; Update mine coords. addd 8,u std 4,u ldd 6,u addd 10,u std 6,u ; ; This block of code draws a mine, using ; information in the mine structure element ; pointed to by the u register. draw_a_visible_mine: jsr INT3Q ldx #mine_vector_ptrs lda 1,u ; Mine type asla ldx a,x ; Mine vector list. leay 4,u ; Mine coordinates. ldb 2,u ; Scale factor. jsr move_y_draw_x2 jmp update_mine_ptr ; ; This routine appears to be processing a ; fireball. It checks to see if the fireball ; has reached the edge of the display, and if ; it has, then the fireball is removed; else, ; the fireball is drawn on the display. process_fireball: ldd 4,u ; Fireball reached addd 8,u ; the edge of the bvs remove_fireball ; display? std 4,u ldd 6,u addd 10,u bvs remove_fireball std 6,u jsr INTMAX leay 4,u ; Draw the fireball. ldx #XFRM_FIRE_BALL ldb #0x04 jsr move_y_draw_x2 jmp update_mine_ptr remove_fireball: clr ,u ; Flag that fireball dec NUM_ACTIVE_MINES ; has been jmp update_mine_ptr ; removed. ; ; move_mine_dot () does some sort of ; processing on the mine's coordinates, and ; then draws the mine as a dot. I believe ; that the processing being done is the ; movement of the dot in the x direction, ; after the mine field has been seeded, but ; before the mine dot has reached it's final ; place. draw_mine_as_dot() draws a mine as ; a dot. ; ; For both these routines, the u register ; must point to a structure element ; describing the mine. move_mine_dot: lda 6,u ; Update mines x adda 16,u ; coord & check if it sta 6,u ; has reached final cmpa 17,u ; resting place. bne draw_mine_as_dot; Flag that mine lsr ,u ; dot is at its final ; resting place. draw_mine_as_dot: jsr INT3Q leay 4,u jsr draw_dot7F_ptr_in_y jmp update_mine_ptr ; ; This procedure is called when a mine first ; becomes visible. If the mine is not a ; large mine, then the mine is drawn at full ; scale factor; otherwise, if the mine is a ; large mine, then it will be drawn with a ; steadily increasing scale factor. This ; gives the effect of the mine 'popping' up. mine_becoming_visible: lda 3,u ; Check if this is a cmpa #0x03 ; large mine. bne use_max_scale_factor lda 2,u cmpa 16,u bge use_max_scale_factor adda #0x08 sta 2,u ; Incr scale factor. bra PE61A use_max_scale_factor: lsr ,u ; Flag that mine is lda 16,u ; full size & visible sta 2,u ; Set final scale lda #0x18 ; factor. sta 16,u ; Set up a delay. lda DOTMINE bne PE61A ; More mine dots? lda NWMNVIS ; Reseeding already bne PE61A ; in progress? lda #0x7F ; Set cntr for sta TMR3 ; reseeding since ; only small mines ; are left. PE61A: jmp draw_a_visible_mine ; ; This procedure is used to delay the ; movement of a mine right after it become ; visible. After the delay is over, the mine ; will start moving. delay_B4_moving_mine: dec 16,u ; Decr delay cntr. bne PE624 lsr ,u PE624: jmp draw_a_visible_mine ; ; This procedure processes the activation of ; 2 new mines after a mine has been ; destroyed. If the destroyed mine was a ; small mine, or a fireball, then 2 new mines ; will not be activated. At entry time, the ; 'a' register must contain the type of mine ; to be started up. process_destroyed_mine: clr ,u ; Flag mine as gone. lda 1,u cmpa #0x04 ; If fireball, don't beq PE644 ; start up new mines. ldb 3,u decb ; If small mine, do beq PE644 ; not start up new pshs a,dp ; mines. lda #0xC8 tfr a,dp lda ,s ; Get type of mine. jsr activate_a_mine jsr activate_a_mine puls a,dp PE644: jmp update_mine_ptr ; ; This routine is responsible for displaying ; the explosion pattern for all active ; explosions. If the command ship is ; exploding, then it will also switch over to ; the next player (eventually). display_explosion_pattern: pshs dp jsr DPIO jsr INTMAX ldu #ACTIVE_EXPLOSIONS; Get ptr to lda #0x0E ; explosion struct. sta TEMP1 ; Set loop counter. check_next_explosion: lda ,u lbeq inc_expl_ptr ldb 4,u ; If explosion scale cmpb 1,u ; factor below max bhs chk_4_cmd_ship_explosion; value, addb #0x03 ; then incr it. stb 4,u ldy 2,u ldx #explosion ; Draw explosion. jsr move_y_draw_x chk_4_cmd_ship_explosion: tsta ; Cmd ship explosion lbpl check_4_expired_explosion; if bit ; 0x80 is set. dec SHIP_EXPLODING_CNTR; Stop when lbeq dead_ship ; cntr reaches zero. lda FRAMLO anda #0x01 ; Every other pass bne draw_expl_cmd_ship; incr scale inc SHIP_EXP_SCALE; factor used to ; draw cmd ship. draw_expl_cmd_ship: lda SHIP_EXP_SCALE; Draw the cmd ship ldy #0x7F00 ; in pieces. ldx #cmd_ship_pt1 jsr draw_cmd_ship_fragment ldy #0x6080 ldx #cmd_ship_pt2 jsr draw_cmd_ship_fragment ldy #0x8050 ldx #cmd_ship_pt3 jsr draw_cmd_ship_fragment ldy #0xA080 ldx #cmd_ship_pt4 jsr draw_cmd_ship_fragment bra inc_expl_ptr ; ; This routine is called after a ship has ; been destroyed. The number of ships for ; the active player, kept in CPXSHP, will be ; decremented. If more than one player is ; playing, then save the active players ship ; count in a memory location (P1XSHP for ; player 1, and P2XSHP for player 2), and ; then determine who's turn it now is. dead_ship: dec CPXSHP ; Decr ship count. clr NUM_ACTIVE_MINES clr DOTMINE lda PLAYRS ; If > 1 player, then beq check_ship_count; ; save active lda ACTPLY ; players ship count. lsra ldx #P1XSHP ldb CPXSHP stb a,x lda P1XSHP ; See who's turn it bne next_player ; is; skip player if lda P2XSHP ; no more ships. beq flag_no_ships_left next_player: lda ACTPLY ; Incr active player adda #0x02 ; indicator. anda #0x02 sta ACTPLY lsra ; Load ship count for ldx #P1XSHP ; new player. ldb a,x stb CPXSHP beq next_player ; ; This routine checks to see if the active ; player has any ships left, after the ; command ship has exploded. check_ship_count: lda CPXSHP bne explosion_expired flag_no_ships_left: lda #0x01 ; Flag 'game over' sta GAMEOVR ; if no ships left. bra explosion_expired ; ; This routine checks to see if the explosion ; has expired. An explosion expires when its ; scale factor surpasses a preset maximum ; value. check_4_expired_explosion: ldb 4,u ; See if scale factor cmpb 1,u ; has reached the blo inc_expl_ptr; max value. explosion_expired: clr ,u dec CMD_SHIP_EXPLODING; Flag ; completion of cmd ; ship explosion. inc_expl_ptr: leau 5,u dec TEMP1 lbne check_next_explosion jsr make_misc_sounds bra draw_tiny_ships ; Draw the tiny ships in lower righthand ; corner . PE711: pshs dp jsr DPIO draw_tiny_ships: jsr INT3Q ldx #0x8038 ; Position for first stx TEMP2 ; ship; don't bother lda CPXSHP ; if active player beq rotate_fireball_vectors; ; has no sta TEMP1 ;ships left. PE727: dec TEMP1 beq rotate_fireball_vectors; ; Exit lda TEMP3 ; when all ships drawn. adda #0x06 ; Incr x coord. sta TEMP3 ldb #0x04 ldy TEMP2 ldx #command_ship jsr move_y_draw_x; Draw tiny md ship. bra PE727 ; ; This routine rotates the fireball vector ; list. Also, it checks to see whether this ; level has been cleared. rotate_fireball_vectors: puls dp direct $C8 lda FRAMLO anda #0x01 asla asla asla ldx #fireball ldu #XFRM_FIRE_BALL jsr PROT ; ; This block of code determines whether ; or not the main loop should be ; exited. If the cmd ship is disabled, ; or if the player has cleared the ; level, then the main loop will be ; exited (this is flagged by clearing ; the carry bit. ldb CMD_SHIP_EXPLODING; Cmd ship bne PE767 ; exploding? lda CS_DIS ; Cmd ship disabled? bne PE764 ldb NUM_ACTIVE_MINES; Check # of bne PE767 ; active mines. ldb DOTMINE ; Check # of dot bne PE767 ; mines. PE764: andcc #0xFE ; Flag to force rts ; 'exit main loop'. PE767: orcc #0x01 ; Resume main loop. rts ; ; This routine is responsible for drawing a ; single fragment of the exploding command ; ship. At entry, 'a' = scale factor, ; 'y' = pen position, and 'x' = ptr to ; vector list. direct $D0 draw_cmd_ship_fragment: pshs a,x,y ldx #SHIP_YX ; Move pen to cmd jsr POSWID ; ship location. lda ,s sta T1LOLC ; Set scale factor. tfr y,d jsr POSITN ; Move pen to pos in ldb #0x0C ; y register. ldx 1,s jsr TPACK ; Draw vector list puls a,x,y,pc ; pointed to by x ; register. ; ; This routine is called after a bullet has ; hit something, or the command ship collides ; with something. It will search through the ; explosion structure, looking for an empty ; slot. When it finds one, it will fill it ; with the information passed in. At entry ; time, 'a' = type of explosion and the scale ; factor to use, 'b' = the max scale factor ; to be used, and 'x' contains the position ; for the explosion. If the hi bit of 'a' is ; set, then that flags that it is the command ; ship exploding; the lower 7 bits are used to ; specify the initial scale factor. direct $C8 add_an_explosion: pshs a,b,x ldx #ACTIVE_EXPLOSIONS lda #0x0E PE78B: ldb ,x ; Find empty slot. beq found_empty_exp_slot leax 5,x deca bne PE78B bra PE7B3 found_empty_exp_slot: lda ,s ; Set explosion type. anda #0x80 inca sta ,x ; Cmd ship explosion? bpl PE7A1 inc CS_DIS ; Flag that cmd ship ; is disabled. PE7A1: lda ,s anda #0x7F ; Save starting scale sta 4,x ; factor. lda 1,s sta 1,x ldd 2,s ; Save maximum scale std 2,x ; factor. inc CMD_SHIP_EXPLODING; Flag cmd ship ; exploding. inc MAKE_EXPL_SOUND; Flag that ; explosion sound ; should be made. PE7B3: puls a,b,x,pc ; ; This routine is responsible for calculating ; a rise and run for an object whose angle of ; travel is in the 'b' register, and whose ; velocity is in the 'a' register. The rise ; is returned in the 'y' register, and the ; run is returned in the 'x' register. calc_rise_run1: pshs a,b,x,y jsr LNROT sta 4,s sex aslb rola aslb rola aslb rola std 2,s ldb 4,s sex aslb rola aslb rola aslb rola std 4,s puls a,b,x,y,pc ; ; This routine also calculates some sort of ; rise & run pair. The same parameters are ; expected at entry time, and the values are ; returned in the same registers. calc_rise_run2: pshs a,b,x,y bsr calc_rise_run1 ldd -4,s aslb rola std 4,s ldd -6,s aslb rola std 2,s puls a,b,x,y,pc ; ; This routine is called each time a new mine ; level is started. It initializes ; everything necessary. init_RAM_for_new_level: lda #0xD0 tfr a,dp direct $D0 jsr INTPSG lda #0xC8 tfr a,dp direct $C8 clr TMR1 ; Clear all 4 jump clr TMR2 ; counters. clr TMR3 clr TMR4 ldx #ACTIVE_BULLETS; Clear level PE7FA: clr ,x+ ; specific RAM. cmpx #MOTION_DOT_PTRS bne PE7FA ldd #0x0000 std NXMINEY std NXMINEX std MINERIS std MINERUN sta RESEED sta CS_DIS ; Clear cmd ship ; disabled flag. sta GAMEOVR ; Clear 'no ships' ; flag. sta NMACTBL ; Clear active bullet ; counter. sta NUM_ACTIVE_MINES sta CMD_SHIP_EXPLODING; Clear cmd ; ship exploding flag sta SHIP_EXP_SCALE; Clear destroyed ; cmd ship scale ; factor. ldb #0x40 stb SHIP_EXPLODING_CNTR; Init cmd ; ship exploding loop ; counter . sta DOTMINE ; Clear # of dot ; mines. sta NWMNVIS ; Clear mine ; activated during ; reseeding flag. ldx #0x0800 stx ENDCNTR ; Set end of game ; loop counter. lda #0x07 sta RESEDCT ; Init # of mines to ; be reseeded. ldx #ind_init_screen_reseeding stx T3FUNC ; Init jump location ; for reseeding. ldd #0x0000 std SHIP_Y ; Clear cmd ship's std SHIP_X ; position. clear_cmd_ship_xformation: ldd #0x0000 sta SHPANGL ; Clear rotation cntr std SHIP_RISE_MOVING std SHIP_RUN_MOVING sta SHPVEL ; Clear cmd ships ; velocity. sta SHPANG2 std SHPRIS2 std SHPRUN2 sta SHPANG4 sta SHPANG3 ; ; This block of code takes the vector list ; describing the command ship, and applies a ; rotation transformation to them. The ; current rotation value is in SHPANGL, and ; the transformed vector list is stored in ; the buffer starting at XFRMSHP. rotate_cmd_ship: lda SHPANGL ldx #command_ship ldu #XFRMSHP jsr PROT lda #0x7F ldb SHPANGL jsr calc_rise_run2 sty TRUE_SHIP_RISE stx TRUE_SHIP_RUN rts ; ; This routine is called after the active ; player clears a mine field level. This ; routine will slowly bring the command ship ; back to the center of the screen. As this ; is being done, a series of dots will be ; drawn to simulate motion. bring_ship_to_center: pshs x,y pshs dp jsr DPIO direct $D0 jsr INTPSG puls dp direct $C8 lda #0xA0 sta TEMP1 ; Set loop counter. PE876: lda SHIP_Y beq PE884 ; Modify y coord for bmi PE87F ; command ship, to deca ; force it back to 0. bra PE880 PE87F: inca PE880: sta SHIP_Y clr SHIP_YL PE884: lda SHIP_X ; Modify x coord for beq PE892 ; command ship, to bmi PE88D ; force it back to 0. deca bra PE88E PE88D: inca PE88E: sta SHIP_X clr SHIP_XL PE892: lda SHPANGL ; Modify rotation beq PE8A2 ; value for cmd ship, cmpa #0x1F ; to force it back bgt PE89D ; to 0. deca bra PE89E PE89D: inca PE89E: anda #0x3F sta SHPANGL ; This loop, repeated 8 times (once for each ; scale factor in the array) increaments each ; of the scale factors for the motions dots ; by 3. PE8A2: jsr PE2F2 ldx #MOTION_DOT_SCALES ldb #0x08 PE8AA: lda ,x adda #0x03 sta ,x+ decb bne PE8AA pshs dp jsr DPIO direct $D0 jsr display_both_scores clrb lda #0x20 jsr simulate_motion1 jsr modify_motion_scales puls dp direct $C8 ; Repeat the above until the ship is ; centered. lda SHIP_Y lbne PE876 lda SHIP_X lbne PE876 lda SHPANGL lbne PE876 dec TEMP1 lbne PE876 jsr init_RAM_for_new_level puls x,y,pc ; ; This routine initializes the two arrays ; (MOTION_DOT_PTRS and MOTION_DOT_SCALES) ; which contain the data needed to produce ; the motion dots (the dots displayed as the ; ship moves from one level to the next). ; The 8 entries in MOTION_DOT_PTRS are ; pointers to the 8 sets of required dots. ; The 8 entries in MOTION_DOT_SCALES are the ; corresponding scale factors. init_motion_dots: ldx #motion_dots ldy #MOTION_DOT_PTRS ldu #MOTION_DOT_SCALES ldb #0x08 lda #0x16 PE8F1: stx ,y++ leax 8,x sta ,u+ adda #0x0F decb bne PE8F1 rts ; ; modify_motion_scales() increments each of ; the 8 motion scale factors, and then draws ; the new motion dots. simulate_motion1() ; and simulate_motion2() both draw the ; current motion dots. The motion dots will ; only be drawn if the scale factor is > the ; value specified in the 'a' register, and ; if (scale - 'b') > 0. modify_motion_scales: pshs a,b,dp,x ldx #MOTION_DOT_SCALES lda #0x08 PE904: inc ,x+ ; Incr each of the deca ; scale factors. bne PE904 bra simulate_motion2 simulate_motion1: pshs a,b,dp,x simulate_motion2: lda #0xD0 tfr a,dp direct $D0 lda #0x09 ; Set loop counter. pshs a PE915: dec ,s bne PE920 jsr ZERGND puls a puls a,b,dp,x,pc PE920: jsr ZERGND lda #0x03 ; LIST holds # of sta LIST ; dots to draw (4). lda ,s deca ldx #MOTION_DOT_SCALES ldb a,x andb #0x7F ; Make sure scale cmpb 1,s ; factor is within bls PE915 ; specified range. subb 2,s ble PE915 stb T1LOLC ; Set hardware scale ; factor. ldx #MOTION_DOT_PTRS; Draw dot list. asla ; Convert loop cntr ldx a,x ; to a word offset. jsr INTMAX jsr DIFDOT bra PE915 ; ; This routine is responsible for drawing the ; hyperspace dot during a hyperspace. It ; draws the 8 sets of motion dots, using a ; decreasing scale factor. At entry, the 'b' ; register contains the minimum scale factor ; to be used. draw_hyperspace_motion_dots: pshs a,b,dp,x lda #0xD0 tfr a,dp direct $D0 lda #0x09 ; Push loop cntr on pshs a ; the stack. next_set_of_dots: dec ,s bne draw_the_dots jsr ZERGND puls a puls a,b,dp,x,pc draw_the_dots: jsr ZERGND lda #0x03 sta LIST ; # of dots to draw. ldx #SHIP_YX jsr POSWID ldb ,s aslb aslb addb 2,s ; Calc scale factor. ble next_set_of_dots andb #0x7F stb T1LOLC ; Set scale factor. ldx #MOTION_DOT_PTRS lda ,s ; Draw appropriate deca ; set of dots. asla ldx a,x jsr INTMAX jsr DIFDOT bra next_set_of_dots ; ; Generate 2 random numbers (1 byte each), ; and return them in a and b. The range for ; the two numbers is: ; ; 0x80 <= first # <= 0x7F (a register) ; 0xA0 <= second # <= 0x60 (b register) direct -1 MS_get_2_random_nums: pshs a,b jsr RANDOM sta ,s PE991: jsr RANDOM cmpa #0x60 bgt PE991 cmpa #0xA0 blt PE991 sta 1,s puls a,b rts ; ; This routine randomly activates a single ; mine. At entry, the 'a' register must ; contain the type of mine to be activated, ; while the 'b' register must contain the ; generation number for the mine (i.e. large, ; medium, or small). direct $C8 activate_a_mine: pshs a,b,x,y,u lda DOTMINE ; Check if there are lbeq PEA3C ; any dot mines; if dec DOTMINE ; not, then return. jsr RANDOM ; Generate random idx anda #0x1F ; into mine array. PE9B0: sta ETMP9 cmpa #0x1B bls PE9BA suba #0x04 bra PE9B0 PE9BA: ldb #0x12 ; Multiple offset by mul ; element size. addd #MINEBUF tfr d,u lda ,u ; See if this slot is anda #0xC0 ; already being used. bne init_a_visible_mine; If so, check inc ETMP9 ; next slot; else use lda ETMP9 ; this slot. cmpa #0x1B ble PE9BA clr ETMP9 clra bra PE9BA init_a_visible_mine: lda ,s ; Save mine type. sta 1,u ldx #mine_values asla ldy a,x sty ETMP7 ; Save mine value. ldb #0x20 stb ,u ldx #mine_velocity lda 1,s ; Save mine velocity. ldb a,x stb ETMP9 ldx #final_mine_scale_factor ldb a,x stb 16,u ; Save scale factor. sta 3,u ; Save generation #. ldx #mine_sizes asla ldy a,x sty 12,u ; Save mine's size. ldx #extra_mine_value ldy a,x sty ETMP5 ; Get any extra value cmpa #0x06 ; for mine's size. bne PEA13 inc MAKE_NEW_MINE_SND; Flag that a ; sound should be ; made. PEA13: lda ETMP6 adda ETMP8 daa ; Generate lo byte sta 15,u ; of score. lda ETMP5 adca ETMP7 daa ; Generate hi byte sta 14,u ; of score. lda ETMP9 jsr MS_random_num_4_to_3C jsr calc_rise_run1 sty 8,u ; Save the rise. stx 10,u ; Save the run. inc NUM_ACTIVE_MINES; Incr 'active ; mine' cntr. lda NWMNVIS beq PEA3C lda #0xFF sta TMR1 lda #0x03 sta LOOPCTR PEA3C: puls a,b,x,y,u,pc ; ; Generate a random number between 4 and ; 0x3C. The result is returned in the b ; register. direct -1 MS_random_num_4_to_3C: pshs a,b jsr RANDOM tfr a,b anda #0x30 sta 1,s andb #0x0F cmpb #0x04 bhs PEA51 addb #0x04 PEA51: cmpb #0x0C bls PEA57 subb #0x04 PEA57: addb 1,s stb 1,s puls a,b,pc ; ; Force the scale factor to 0x7F, then ; draw a dot at the position contained ; in the y register. direct $D0 draw_dot7F_at_y: pshs a,b lda #0x7F sta T1LOLC tfr y,d jsr DOTAB jsr ZERGND puls a,b,pc ; ; Force the scale factor to 0x7F, then draw a ; dot at the position pointed to by the y ; register (y coord = (0,y), x coord = (2,y)) direct $D0 draw_dot7F_ptr_in_y: pshs a,b lda #0x7F sta T1LOLC lda ,y ldb 2,y jsr DOTAB jsr ZERGND puls a,b,pc ; ; Move the pen to the position specified ; in the y register, then draw the vector ; list pointed to by the x register; the ; scale factor is in the b register. direct -1 move_y_draw_x: pshs a,b,x tfr y,d jsr POSITD ldb 1,s jsr TPACK puls a,b,x,pc ; ; Move the pen to the position pointed to by ; the y register, and draw the list of ; vectors pointed to by the x register; the ; scale factor to be used is in the b reg. ; (y coord = (0,y), x coord = (x,y)) direct -1 move_y_draw_x2: pshs a,b,x tfr y,x jsr POSWID ldb 1,s ldx 2,s jsr TPACK puls a,b,x,pc ; ; Force the scale factor to 0x7F, then print ; a single string (upto a 0x80). The pointer ; to the string block is contained in the ; u register. direct -1 MS_print_1_string7F: pshs a,b,x,u lda #0x7F sta T1LOLC jsr RSTSIZ puls a,b,x,u,pc ; ; Move the pen to the position specified in ; the y register, then print a string. The ; pointer to the string (not a string block) ; is in the u register. direct -1 move_y_print_string: pshs a,b,x,u tfr y,d jsr POSITD jsr RASTER puls a,b,x,y,pc ; ; Use the value in ACTPLY (the active player) ; to determine which players score to display ; and then display the score string. direct -1 display_active_players_score: jsr INTMAX ldd #0xFC38 std SIZRAS ; Specify ht & width. lda ACTPLY ldy #score_string_positions ldy a,y ; Load string pos. ldu #score_string_pointers ldu a,u ; Load score string. bsr move_y_print_string rts ; ; Display the score for both players direct -1 display_both_scores: jsr INTMAX ldd #0xFC38 std SIZRAS ; Set ht & width. ldy #0x7FA0 ; Load y&x pos. ldu #SCOR1 ; Player 1 score. bsr move_y_print_string lda PLAYRS ; Display player 2 beq PEAEF ; score? ldy #0x7F10 ; Load y&x pos. ldu #SCOR2 ; Player 2 score. bsr move_y_print_string PEAEF: rts ; ; This routine is responsible for reading the ; current states of the joystick and buttons. ; Next, it will check each of the four ; indirect jump counters, and if any of them ; equal 0 after being decremented, then the ; appropriate indirect handling routine will ; be called. The four indirect counters, and ; their corresponding handler routines are ; shown below: ; ; counter handler ; ------- ------- ; C89C C89D-C89E ; C89F C8A0-C8A1 ; C8A2 C8A3-C8A4 ; C8A5 C8A6-C8A7 ; direct -1 process_indirect_jumps: jsr FRWAIT pshs dp jsr DEFLOK jsr display_active_players_score ; Set mask and read the switches. lda SATUS jsr DBNCE ; Set enable flags and read joystick. ldd SJOY std EPOT0 std EPOT2 jsr JOYBIT lda #0xC8 tfr a,dp direct $C8 lda TMR1 beq PEB1D dec TMR1 bne PEB1D jsr [T1FUNC] PEB1D: lda TMR2 beq PEB29 dec TMR2 bne PEB29 jsr [T2FUNC] PEB29: lda TMR3 beq PEB35 dec TMR3 bne PEB35 jsr [T3FUNC] PEB35: lda TMR4 beq PEB41 dec TMR4 bne PEB41 jsr [T4FUNC] PEB41: puls dp,pc ; ; This routine check to see if any of the ; bullets have hit a mine or a fireball or ; the enemy ship. If something is hit, then ; the active player's score will be modified. direct $C8 check_bullets_for_hits: lda NMACTBL ; Don't check if no beq PEB59 ; active bullets. ldy #ACTIVE_BULLETS lda #0x04 sta TEMP1 ; Set loop counter. check_for_active_bullet: tst ,y ; Is bullet active? bne check_enemy_ship_4_hit inc_bullet_ptr2: leay 10,y ; Pt to next bullet. dec TEMP1 bne check_for_active_bullet PEB59: rts direct $C8 check_enemy_ship_4_hit: lda RESEED ; Only check if enemy beq check_mines_for_hit; ship showing pshs y lda 5,y ldb 7,y tfr d,x ; Bullet position. ldd #0x0616 ; Ht/2 and Wid/2 of ; enemy ship. ldy MSHP_YX ; Pos of enemy ship. jsr BXTEST ; Check for hit. puls y bhs check_mines_for_hit clr ,y ; HIT - flag bullet ; as dead. clr RESEED ; Flag enemy ship as ; dead. clr TMR3 ; Clear jump cntr. ldx #score_string_pointers lda ACTPLY ldx a,x ldd #0x1000 ; Add 1000 to score. jsr SCRADD lda #0x30 ldb #0x70 ldx MSHP_YX jsr add_an_explosion dec NMACTBL ; Decr # of active bra PEB59 ; bullets. ; ; This routine checks to see if a bullet hit ; any of the active mines or fireballs. direct $C8 check_mines_for_hit: ldu #MINEBUF ; Load mine info. lda #0x1C sta TEMP2 ; Set loop counter. check_for_active_mine: lda ,u anda #0x3F ; Is mine active? bne check_this_mine inc_mine_ptr2: leau 0x12,u ; Point to next mine. dec TEMP2 bne check_for_active_mine bra inc_bullet_ptr2 check_this_mine: pshs y lda 5,y ldb 7,y tfr d,x ; Bullet coords. lda 4,u ldb 6,u ; Mine coords. tfr d,y ldd 12,u ; Ht & width of mine. jsr BXTEST ; Carry set = hit, puls y ; else miss. bhs inc_mine_ptr2 lda 1,u ; fireball mine? anda #0x02 beq not_a_fireball_mine ldx #score_string_pointers lda ACTPLY ldx a,x ldd 14,u ; Add mines value to jsr SCRADD ; players score. inc UNKNOWN1 lda 4,u ldb 6,u tfr d,x lda 2,u ldb #0x20 jsr add_an_explosion ldd #0x0110 ; Init fireball score std 14,u lda SHIP_Y suba 4,u ldb SHIP_X subb 6,u jsr CMPASS suba #0x10 tfr a,b pshs y lda #0x3F jsr calc_rise_run1 sty 8,u ; Calculate rise/run stx 10,u ; for fireball. puls y clr ,y ; Flag bullet dead. ldd #0x0404 ; Set Ht/2 & Wid/2 std 12,u ; for fireball. lda 1,u ldb 3,u ; Decr generation # decb ; for this mine and ; don't start another ; if it = 0. beq start_a_fireball jsr activate_a_mine jsr activate_a_mine start_a_fireball: lda #0x04 ; Flag that this is a sta 1,u ; fireball. dec NMACTBL ; Decr active bullet jmp inc_bullet_ptr2; counter. ; ; This processes a hit on a non-fireball type ; mine. not_a_fireball_mine: lda #0x01 sta ,u clr ,y ; Flag bullet dead. ldx #score_string_pointers lda ACTPLY ldx a,x ; Add mines value to ldd 14,u ; players score. jsr SCRADD lda 4,u ldb 6,u tfr d,x lda 2,u ldb #0x40 jsr add_an_explosion dec NUM_ACTIVE_MINES; Decr active mine ; counter. dec NMACTBL ; Decr active bullet ; counter. jmp inc_bullet_ptr2 ; ; This routine check each active mine to see ; if it has collided with the command ship. direct $C8 check_ship_4_mine_collision: lda CS_DIS ; Do only if cmd ship bne PEC63 ; not already dead. lda HYPERON ; Do only if bne PEC63 ; hyperspace inactive ldy #MINEBUF lda #0x1C sta TEMP1 ; Set up loop cntr. PEC56: lda ,y anda #0x3F bne check_this_active_mine inc_mine_ptr3: leay 0x12,y dec TEMP1 bne PEC56 PEC63: rts check_this_active_mine: pshs y lda SHIP_Y ldb SHIP_X ; Load cmd ship's tfr d,x ; position. lda 4,y ldb 6,y ldy 12,y ; Load mine position. exg y,d jsr BXTEST puls y bhs inc_mine_ptr3 clr ,y ; Flag mine is dead. clr DOTMINE lda SHIP_Y ldb SHIP_X tfr d,x lda 2,y ora #0x80 ldb #0x30 jsr add_an_explosion inc MAKE_EXPL_SOUND ; Flag for an ; explosion snd. dec NUM_ACTIVE_MINES; Decr active ; mine counter. bra PEC63 ; ; This routine checks to see if the command ; ship has collided with the enemy ship ; during reseeding. direct $C8 check_ship_4_enemy_collision: lda CS_DIS ; Do only if cmd ship bne PECB2 ; not disabled. lda HYPERON ; Don't do if bne PECB2 ; hyperspace active. lda RESEED ; Check only if enemy beq PECB2 ; ship visible. lda SHIP_Y ldb SHIP_X tfr d,x ; Cmd ship location. ldd #0x0616 ; Size of enemy ship. ldy MSHP_YX ; Enemy ship location jsr BXTEST blo cmd_and_enemy_ship_collision PECB2: rts cmd_and_enemy_ship_collision: clr RESEED ; Flag enemy ship no ; longer visible. clr TMR3 lda SHIP_Y ldb SHIP_X tfr d,x lda #0x08 ora #0x80 ldb #0x30 jsr add_an_explosion inc MAKE_EXPL_SOUND; Enable explosion ; sound. rts ; ; This routine is responsible for making ; miscellaneous sound, such as when an ; explosion occurs, or a bullet is fired. direct -1 make_misc_sounds: lda MKMVSND beq PECD6 clr MKMVSND ; Make cmd ship ; movement snd. ldu #cmd_ship_movement_sound bra make_the_misc_sound PECD6: lda MAKE_EXPL_SOUND beq PECE3 clr MAKE_EXPL_SOUND ; Make explosion ldu #explosion_sound ; sound. bra make_the_misc_sound PECE3: lda MKBLSND beq PECF0 clr MKBLSND ; Make bullet ldu #bullet_sound ; firing sound. bra make_the_misc_sound PECF0: lda MAKE_NEW_MINE_SND beq PED00 PECF5: clr MAKE_NEW_MINE_SND clr MKHYSND ; Make sound of ldu #mine_pop_sound ; mine 'popping' bra make_the_misc_sound; up. PED00: lda MKHYSND bne PECF5 ; Make hyperspace snd bra PED0A make_the_misc_sound: jsr PSGLST PED0A: ldb REG0 addb #0x10 cmpb #0xA0 bhs PED1A lda #0x00 jsr WRREG bra PED20 PED1A: ldd #0x0800 jsr WRREG PED20: ldb REG2 addb #0x20 cmpb #0xF0 bhs PED30 lda #0x02 jsr WRREG bra PED36 PED30: ldd #0x0900 jsr WRREG PED36: rts cmd_ship_movement_sound: db 0x00 db 0x10 db 0x01 db 0x00 db 0x06 db 0x1F db 0x07 db 0x06 db 0x08 db 0x0F db 0xFF bullet_sound: db 0x02 db 0x39 db 0x03 db 0x00 db 0x06 db 0x1F db 0x07 db 0x05 db 0x09 db 0x0F db 0xFF explosion_sound: db 0x06 db 0x1F db 0x07 db 0x07 db 0x0A db 0x10 db 0x0B db 0x00 db 0x0C db 0x38 db 0x0D db 0x00 db 0xFF mine_pop_sound: db 0x00 db 0x00 db 0x01 db 0x00 db 0x02 db 0x30 db 0x03 db 0x00 db 0x04 db 0x00 db 0x05 db 0x00 db 0x06 db 0x1F db 0x07 db 0x3D db 0x08 db 0x00 db 0x09 db 0x0F db 0x0A db 0x00 db 0x0B db 0x00 db 0x0C db 0x00 db 0x0D db 0x00 db 0xFF ; Start of Mine Storm music block MS_music: dw MS_music_header1 dw MSCHDR7 db 0x00 db 0x19 db 0x01 db 0x19 db 0x00 db 0x19 db 0x01 db 0x32 db 0x00 db 0x19 db 0x01 db 0x19 db 0x00 db 0x19 db 0x06 db 0x19 db 0x05 db 0x19 db 0x00 db 0x80 MS_music_header1: dw 0xFFEE db 0xDD db 0xCC db 0xBB db 0xAA db 0x99 db 0x88 db 0x77 db 0x77 db 0x77 db 0x77 db 0x77 db 0x77 db 0x77 db 0x77 ; Pointers to player's score string score_string_pointers: dw SCOR1 ; Player 1 dw SCOR2 ; Player 2 ; Y,X positions for drawing player's ; score string. score_string_positions: db 0x7F ; Player 1 rel y score pos db 0xA0 ; Player 1 rel x score pos db 0x7F ; Player 2 rel y score pos db 0x10 ; Player 2 rel x score pos ; Pointers to player's mine field # string mine_field_level_pointers: dw P1LVL ; Player 1 dw P2LVL ; Player 2 ; This contains the information describing ; which mines are to appear at the first 13 ; mine field levels. The values map a ; follows: ; ; 0 = dumb mine ; 1 = magnetic mine ; 2 = fireball mine ; 3 = magnetic fireball mine ; mines_at_level_x: db 0x00 ; level 1 db 0x00 db 0x00 db 0x00 db 0x02 ; level 2 db 0x00 db 0x00 db 0x00 db 0x01 ; level 3 db 0x00 db 0x00 db 0x00 db 0x03 ; level 4 db 0x00 db 0x00 db 0x00 db 0x02 ; level 5 db 0x01 db 0x00 db 0x00 db 0x02 ; level 6 db 0x03 db 0x00 db 0x00 db 0x01 ; level 7 db 0x03 db 0x00 db 0x00 db 0x02 ; level 8 db 0x02 db 0x00 db 0x00 db 0x01 ; level 9 db 0x01 db 0x00 db 0x00 db 0x03 ; level 10 db 0x03 db 0x00 db 0x00 db 0x02 ; level 11 db 0x02 db 0x02 db 0x00 db 0x01 ; level 12 db 0x01 db 0x01 db 0x00 db 0x03 ; level 13 db 0x03 db 0x03 db 0x00 db 0x80 motion_dots: db 0xC8 db 0x40 db 0x3F db 0x00 db 0x20 db 0x80 db 0x10 db 0x1F db 0x3F db 0x3F db 0x00 db 0xBF db 0xBF db 0xBF db 0xC0 db 0x20 db 0x48 db 0x08 db 0xF8 db 0x30 db 0xA8 db 0x10 db 0xD0 db 0xA0 db 0xBF db 0xBF db 0x00 db 0x3F db 0x3F db 0x48 db 0x20 db 0x80 db 0x00 db 0xB0 db 0x48 db 0x38 db 0xFB db 0x38 db 0x80 db 0x28 db 0x30 db 0x48 db 0x80 db 0x80 db 0x45 db 0xF0 db 0x28 db 0x7F db 0x3F db 0xBF db 0xA5 db 0x00 db 0xD0 db 0x60 db 0x20 db 0x28 db 0xB8 db 0x40 db 0x15 db 0x80 db 0x40 db 0xF8 db 0x40 db 0x18 mine_field: db -6 ; height db 56 ; width db -32 ; rel y db -56 ; rel x db "MINE FIELD", 0x80; game_over: db -6 ; height db 56 ; width db -32 ; rel y db -40 ; rel x db "GAME OVER",0x80; dumb_mine: db 0x00 db 0x10 db 0x00 db 0xFF db 0x20 db 0xA0 db 0xFF db 0xC0 db 0x40 db 0xFF db 0x90 db 0x20 db 0xFF db 0x70 db 0x20 db 0xFF db 0x50 db 0x50 db 0xFF db 0xD0 db 0x90 db 0x01 magnetic_mine: db 0x00 db 0x20 db 0x00 db 0xFF db 0x30 db 0xB0 db 0xFF db 0xB0 db 0x30 db 0xFF db 0xB0 db 0xD0 db 0xFF db 0x30 db 0x50 db 0xFF db 0xD0 db 0x50 db 0xFF db 0x50 db 0xD0 db 0xFF db 0x50 db 0x30 db 0xFF db 0xD0 db 0xB0 db 0x01 fireball_mine: db 0xFF db 0x00 db 0x00 db 0x00 db 0x30 db 0x00 db 0xFF db 0x10 db 0xC0 db 0xFF db 0xC0 db 0x10 db 0xFF db 0xC0 db 0xF0 db 0xFF db 0x10 db 0x40 db 0xFF db 0xF0 db 0x40 db 0xFF db 0x40 db 0xF0 db 0xFF db 0x40 db 0x10 db 0xFF db 0xF0 db 0xC0 db 0x01 magnetic_fireball_mine: db 0xFF db 0x00 db 0x00 db 0x00 db 0xF0 db 0xD0 db 0xFF db 0xC0 db 0x40 db 0xFF db 0x20 db 0x00 db 0xFF db 0x40 db 0x40 db 0xFF db 0x00 db 0xE0 db 0xFF db 0x40 db 0xC0 db 0xFF db 0xE0 db 0x00 db 0xFF db 0xC0 db 0xC0 db 0xFF db 0x00 db 0x20 db 0x01 fireball: db 0x00 db 0x3F db 0x00 db 0xFF db 0x80 db 0x00 db 0x00 db 0x3F db 0x3F db 0xFF db 0x00 db 0x80 db 0x01 explosion: db 0xFF db 0x7F db 0x20 db 0x00 db 0xC0 db 0x10 db 0xFF db 0xC0 db 0xD0 db 0xFF db 0x20 db 0x7F db 0x00 db 0xE0 db 0xC0 db 0xFF db 0x00 db 0xC0 db 0xFF db 0xE0 db 0x30 db 0x00 db 0xC0 db 0x00 db 0xFF db 0x60 db 0xCD db 0xFF db 0xA0 db 0x00 db 0x00 db 0x20 db 0xD0 db 0xFF db 0x3C db 0x30 db 0xFF db 0x00 db 0x82 db 0x00 db 0x30 db 0x30 db 0xFF db 0xD0 db 0x50 db 0xFF db 0x20 db 0xF0 db 0x01 command_ship: db 0x00 db 0x3F db 0x00 db 0xFF db 0xC4 db 0x08 db 0xFF db 0xD8 db 0xD8 db 0xFF db 0x20 db 0x00 db 0x00 db 0x00 db 0x40 db 0xFF db 0xE0 db 0x00 db 0xFF db 0x28 db 0xD8 db 0xFF db 0x3C db 0x08 db 0x01 cmd_ship_pt1: db 0x00 db 0x3F db 0x00 db 0xFF db 0xC4 db 0x08 db 0x01 cmd_ship_pt2: db 0x00 db 0x04 db 0x08 db 0xFF db 0xD8 db 0xD8 db 0xFF db 0x20 db 0x00 db 0x01 cmd_ship_pt3: db 0x00 db 0x3F db 0x00 db 0xFF db 0xC4 db 0xF8 db 0x01 cmd_ship_pt4: db 0x00 db 0x04 db 0xF8 db 0xFF db 0xD8 db 0x28 db 0xFF db 0x20 db 0x00 db 0x01 enemy_ship_pt1: db 0x00 db 0x20 db 0x00 db 0xFF db 0x00 db 0xD8 db 0xFF db 0xD0 db 0xA8 db 0xFF db 0xF0 db 0x40 db 0xFF db 0x08 db 0x18 db 0xFF db 0x18 db 0xF0 db 0xFF db 0xF0 db 0xB8 db 0x00 db 0x10 db 0x48 db 0xFF db 0x08 db 0x00 db 0xFF db 0xE8 db 0x10 db 0xFF db 0xF8 db 0x00 db 0x00 db 0x08 db 0x00 db 0xFF db 0x00 db 0x06 db 0x00 db 0x10 db 0xFA db 0xFF db 0x08 db 0x00 db 0xFF db 0x00 db 0xF0 db 0x00 db 0x10 db 0x18 db 0xFF db 0xF0 db 0x08 db 0x01 enemy_ship_pt2: db 0x00 db 0x20 db 0x00 db 0xFF db 0x00 db 0x28 db 0xFF db 0xD0 db 0x58 db 0xFF db 0xF0 db 0xC0 db 0xFF db 0x08 db 0xE8 db 0xFF db 0x18 db 0x10 db 0xFF db 0xF0 db 0x48 db 0x00 db 0x10 db 0xB8 db 0xFF db 0x08 db 0x00 db 0xFF db 0xE8 db 0xF0 db 0xFF db 0xF8 db 0x00 db 0xFF db 0x08 db 0x00 db 0xFF db 0x00 db 0xFA db 0x00 db 0x10 db 0x06 db 0xFF db 0x08 db 0x00 db 0xFF db 0x00 db 0x10 db 0x00 db 0x10 db 0xE8 db 0xFF db 0xF0 db 0xF8 db 0x01 enemy_ship_pt3: db 0xFF db 0x00 db 0xD8 db 0xFF db 0xE8 db 0x08 db 0xFF db 0x00 db 0x40 db 0xFF db 0x18 db 0x08 db 0xFF db 0x00 db 0xD8 db 0x00 db 0x08 db 0xE0 db 0xFF db 0x10 db 0x00 db 0xFF db 0x00 db 0x40 db 0xFF db 0xF0 db 0x00 db 0xFF db 0x00 db 0xC0 db 0x01 simple_enemy_ship: db 0x00 db 0x18 db 0x00 db 0xFF db 0x00 db 0x20 db 0xFF db 0xC8 db 0x70 db 0xFF db 0x10 db 0xA0 db 0xFF db 0x00 db 0xA0 db 0xFF db 0xEC db 0xA4 db 0xFF db 0x39 db 0x6D db 0xFF db 0x00 db 0x20 db 0x01