Prev: A53A Up: Map Next: A73C
A579: Handler: Player Shot
On a 1-in-4 frame, spawn a shot into a free laser slot when FIRE is held, then fly any live shots.
Input
IX Actor slot
Handler_PlayerShot A579 LD A,($5E42) Fetch GameTimer.
A57C AND %00000011 Keep only bits 0-1.
A57E RET NZ Return if this is not a 4th frame.
A57F CALL HandlerControls Call HandlerControls.
A582 BIT 4,A Return if FIRE is not pressed.
A584 RET NZ
Look for a free laser slot.
A585 LD HL,$6000 HL=Laser_Parameter_1.
A588 LD DE,$0018 DE=0018.
A58B LD B,$02 Set a slot counter in B for 02 loops.
Handler_PlayerShot_Loop A58D LD A,(HL) Jump to Handler_PlayerShot_Initialise if this slot is free.
A58E AND A
A58F JR Z,Handler_PlayerShot_Initialise
A591 ADD HL,DE Move onto the next slot.
A592 DJNZ Handler_PlayerShot_Loop Decrease the slot counter by one and loop back to Handler_PlayerShot_Loop until both slots have been tried.
A594 RET Return.
Initialise a new shot from the current actor.
Handler_PlayerShot_Initialise A595 PUSH HL Stash the free slot on the stack.
A596 CALL Copy_Explosion_Template Call Copy_Explosion_Template.
A599 POP HL Restore the free slot from the stack.
A59A LD (HL),$58 Write type 58.
A59C INC HL Move onto the new world X.
A59D INC HL
A59E EX DE,HL Switch the destination into DE.
Look up this actor's entry in the shot table at Handler_PlayerShot_Table.
A59F LD A,(IX+$00) Fetch the actor type.
A5A2 RLCA Rotate it left twice.
A5A3 RLCA
A5A4 AND %00111100 Keep only bits 2-5.
A5A6 LD C,A Create an offset in BC.
A5A7 LD B,$00
A5A9 LD HL,$A68B HL=Handler_PlayerShot_Table.
A5AC ADD HL,BC Add the offset.
Add the table X offset to the actor world X.
A5AD LD A,(HL) Fetch the X offset.
A5AE LD B,$00 Clear B.
A5B0 AND A Jump to Handler_PlayerShot_AddWorldX if the offset is positive.
A5B1 JP P,Handler_PlayerShot_AddWorldX
A5B4 DEC B Sign-extend into B.
Handler_PlayerShot_AddWorldX A5B5 ADD A,(IX+$02) Add the actor world X.
A5B8 INC HL Move onto the next table byte.
A5B9 LD (DE),A Write the new world X.
A5BA INC DE Move onto the high byte.
Work out the high byte of the new world X and the new Y.
A5BB LD A,(IX+$03) Fetch the actor world X high byte.
A5BE ADC A,B Add the sign.
A5BF AND %00011111 Keep only bits 0-4.
A5C1 LD (DE),A Write the high byte.
A5C2 INC DE Move onto the new Y.
A5C3 LD A,(IX+$04) Fetch the actor Y.
A5C6 ADD A,(HL) Add the table Y offset.
A5C7 INC HL Move onto the next table byte.
Write the remaining shot fields and clear the rest of the slot.
Handler_PlayerShot_WriteFields A5C8 LD (DE),A Write the new Y.
A5C9 INC DE Move onto the speed.
A5CA LD A,(HL) Copy the next table byte.
A5CB INC HL
A5CC LD (DE),A Write it and move on.
A5CD INC DE
A5CE LD A,(HL) Copy the next table byte.
A5CF INC HL
A5D0 LD (DE),A Write it and move on.
A5D1 INC DE
Pick the shot colour from the timer at RandomNumber.
A5D2 LD A,($5E40) Fetch RandomNumber.
A5D5 AND %00000011 Keep only bits 0-1.
A5D7 LD BC,$A5EF Point BC at the shot colour table at Handler_PlayerShot_Colours.
A5DA ADD A,C Add the colour index.
A5DB LD C,A Copy the low byte into C.
A5DC LD A,B Fetch the high byte.
A5DD ADC A,$00 Add the carry.
A5DF LD B,A Write it back to B.
A5E0 LD A,(BC) Fetch the colour.
A5E1 LD (DE),A Write it to the shot colour.
A5E2 INC DE Move onto the next field.
A5E3 LD A,$20 A=20.
A5E5 LD (DE),A Write it.
A5E6 INC DE Move on.
Clear the remaining 0F bytes of the slot.
A5E7 LD B,$0F Set a byte counter in B for 0F loops.
A5E9 XOR A Clear A.
Handler_PlayerShot_ClearTail A5EA LD (DE),A Write 00.
A5EB INC DE Move onto the next byte.
A5EC DJNZ Handler_PlayerShot_ClearTail Decrease the byte counter by one and loop back to Handler_PlayerShot_ClearTail until the slot tail is clear.
A5EE RET Return.
The four colours a player shot can be.
Handler_PlayerShot_Colours A5EF DEFB $44 INK:GREEN, PAPER:BLACK (BRIGHT).
The four colours a player shot can be.
A5F0 DEFB $45 INK:CYAN, PAPER:BLACK (BRIGHT).
The four colours a player shot can be.
A5F1 DEFB $46 INK:YELLOW, PAPER:BLACK (BRIGHT).
The four colours a player shot can be.
A5F2 DEFB $47 INK:WHITE, PAPER:BLACK (BRIGHT).
Advance the shot world X from the packed nibble at *IX+10.
Handler_PlayerShot_AdvanceX A5F3 ADD A,(IX+$10) Add the X nibble.
A5F6 LD C,A Stash the sum in C.
A5F7 AND %00001111 Keep only bits 0-3.
A5F9 LD (IX+$10),A Write it back as the X nibble.
A5FC LD A,C Copy the sum into A.
A5FD RRCA Rotate the high nibble down into bits 0-3.
A5FE RRCA
A5FF RRCA
A600 RRCA
A601 AND %00001111 Keep only bits 0-3.
A603 LD B,$00 Clear B.
A605 JR Handler_PlayerShot_WriteX Jump to Handler_PlayerShot_WriteX.
Advance the shot Y from the packed nibble at *IX+11.
Handler_PlayerShot_AdvanceY A607 ADD A,(IX+$11) Add the Y nibble.
A60A LD C,A Stash the sum in C.
A60B AND %00001111 Keep only bits 0-3.
A60D LD (IX+$11),A Write it back as the Y nibble.
A610 LD A,C Copy the sum into A.
A611 RRCA Rotate the high nibble down into bits 0-3.
A612 RRCA
A613 RRCA
A614 RRCA
A615 AND %00001111 Keep only bits 0-3.
A617 JR Handler_PlayerShot_WriteY Jump to Handler_PlayerShot_WriteY.
Count down the shot timer and work out the X step from the shot speed.
Handler_PlayerShot_Fly A619 DEC (IX+$08) Decrease the shot timer by one.
A61C JP Z,StartSmallExplosion Jump to StartSmallExplosion if it has expired.
A61F LD A,(IX+$05) Fetch the shot speed.
A622 AND A Jump to Handler_PlayerShot_AdvanceX if the speed is positive.
A623 JP P,Handler_PlayerShot_AdvanceX
Work out a negative X step when the speed is negative.
A626 ADD A,(IX+$10) Add the X nibble.
A629 LD C,A Stash the sum in C.
A62A AND %00001111 Keep only bits 0-3.
A62C NEG Negate it.
A62E LD (IX+$10),A Write it back as the X nibble.
A631 LD A,C Copy the sum into A.
A632 NEG Negate it.
A634 RRCA Rotate the high nibble down into bits 0-3.
A635 RRCA
A636 RRCA
A637 RRCA
A638 AND %00001111 Keep only bits 0-3.
A63A NEG Negate it.
A63C LD B,$FF B=FF.
Add the X step to the shot's world X.
Handler_PlayerShot_WriteX A63E ADD A,(IX+$02) Add the step to the world X.
A641 LD (IX+$02),A Write it back.
A644 LD A,(IX+$03) Fetch the high byte.
A647 ADC A,B Add the sign.
A648 AND %00011111 Keep only bits 0-4.
A64A LD (IX+$03),A Write the high byte back.
Work out the Y step from the shot thrust.
A64D LD A,(IX+$06) Fetch the shot thrust.
A650 AND A Jump to Handler_PlayerShot_AdvanceY if the thrust is positive.
A651 JP P,Handler_PlayerShot_AdvanceY
Work out a negative Y step when the thrust is negative.
A654 ADD A,(IX+$11) Add the Y nibble.
A657 LD C,A Stash the sum in C.
A658 AND %00001111 Keep only bits 0-3.
A65A NEG Negate it.
A65C LD (IX+$11),A Write it back as the Y nibble.
A65F LD A,C Copy the sum into A.
A660 NEG Negate it.
A662 RRCA Rotate the high nibble down into bits 0-3.
A663 RRCA
A664 RRCA
A665 RRCA
A666 AND %00001111 Keep only bits 0-3.
A668 NEG Negate it.
Handler_PlayerShot_WriteY A66A ADD A,(IX+$04) Add the step to the shot Y.
Destroy the shot if it hits the ground or leaves the play area.
A66D CP $AF Compare it against AF.
A66F JP NC,StartSmallExplosion Jump to StartSmallExplosion if the shot is on the ground.
A672 CP $30 Compare it against 30.
A674 JP C,StartSmallExplosion Jump to StartSmallExplosion if the shot is above the play area.
Store the new Y, flip the shot frame and draw the shot.
A677 LD (IX+$04),A Write the new Y.
A67A LD A,(IX+$00) Fetch the shot type.
A67D XOR %00000001 Flip bit 0.
A67F LD (IX+$00),A Write it back.
A682 CALL DrawObjectSprite Call DrawObjectSprite.
A685 CALL ColouriseSprite Call ColouriseSprite.
A688 JP Handler_PlayerShot_TestSlots Jump to Handler_PlayerShot_TestSlots.
Handler_PlayerShot_Table A68B DEFB $F8,$FC,$C0,$00,$F8,$F9,$C4,$FA Shot table. Each 04-byte entry holds an X offset, a Y offset, a speed and a thrust.
A693 DEFB $F9,$F6,$C7,$E3,$F9,$F4,$CA,$DE
A69B DEFB $FC,$F2,$D3,$D3,$FF,$F0,$DB,$CC
A6A3 DEFB $01,$F0,$E3,$C7,$03,$EE,$EA,$C4
A6AB DEFB $10,$FC,$40,$00,$10,$F9,$3C,$FA
A6B3 DEFB $10,$F5,$39,$E3,$0F,$F3,$36,$DE
A6BB DEFB $0C,$F2,$2D,$D3,$09,$F0,$25,$CC
A6C3 DEFB $08,$EF,$1D,$C7,$05,$ED,$16,$C4
Test the shot against the alien and object slots.
Handler_PlayerShot_TestSlots A6CB LD A,$18 A=18.
A6CD LD ($A726),A Write it over the hit-height compare at A726.
A6D0 LD HL,$61B0 HL=Alien_Slot_1.
A6D3 LD DE,$0018 DE=0018.
A6D6 LD B,$06 Set a slot counter in B for 06 loops.
A6D8 CALL Handler_PlayerShot_ScanSlot Call Handler_PlayerShot_ScanSlot.
Test the object slot at Object_Slot_1 with a hit height of 0C.
A6DB LD A,$0C A=0C.
A6DD LD ($A726),A Write it over the hit-height compare at A726.
A6E0 LD HL,$6108 HL=Object_Slot_1.
A6E3 LD B,$01 Set a slot counter in B for 01 loop.
A6E5 CALL Handler_PlayerShot_ScanSlot Call Handler_PlayerShot_ScanSlot.
Test the object slot at Object_Slot_3 with a hit height of 18.
A6E8 LD A,$18 A=18.
A6EA LD ($A726),A Write it over the hit-height compare at A726.
A6ED LD HL,$6138 HL=Object_Slot_3.
A6F0 LD B,$01 Set a slot counter in B for 01 loop.
Test every slot in this group that is in use.
Handler_PlayerShot_ScanSlot A6F2 LD A,(HL) Fetch the slot type.
A6F3 AND A Test it.
A6F4 PUSH BC Stash BC, DE and HL on the stack.
A6F5 PUSH DE
A6F6 PUSH HL
A6F7 CALL NZ,Handler_PlayerShot_CompareBox Call Handler_PlayerShot_CompareBox if the slot is in use.
A6FA POP HL Restore HL, DE and BC from the stack.
A6FB POP DE
A6FC POP BC
A6FD ADD HL,DE Move onto the next slot.
A6FE DJNZ Handler_PlayerShot_ScanSlot Decrease the slot counter by one and loop back to Handler_PlayerShot_ScanSlot until every slot has been tested.
A700 RET Return.
Compare this slot's box against the shot.
Handler_PlayerShot_CompareBox A701 INC HL Move onto the slot world X.
A702 INC HL
A703 EX DE,HL Switch the slot pointer into DE.
A704 LD A,(DE) Fetch the world X.
A705 INC DE Move onto the high byte.
A706 LD C,A Copy the low byte into C.
A707 LD A,(DE) Fetch the high byte.
A708 INC DE Move onto the Y.
A709 LD B,A Copy the high byte into B.
A70A LD HL,$0008 HL=0008.
A70D ADD HL,BC Add the box offset.
Check the shot is horizontally within reach of the slot.
A70E LD C,(IX+$02) Fetch the shot world X.
A711 LD B,(IX+$03) Fetch the shot world X high byte.
A714 AND A Clear the carry flag.
A715 SBC HL,BC Subtract the shot world X.
A717 LD A,H Fetch the high byte of the difference.
A718 AND %00011111 Keep only bits 0-4.
A71A RET NZ Return if they are on different screens.
A71B LD A,L Fetch the low byte.
A71C CP $10 Return if it is at least 10.
A71E RET NC
Check the shot is vertically within reach of the slot.
A71F LD A,(DE) Fetch the slot Y.
A720 ADD A,$04 Add 04.
A722 SUB (IX+$04) Subtract the shot Y.
A725 CP $18 Compare it against the current hit height.
A727 RET NC Return if the shot missed.
Set the slot's explode flag, clear the shot and stop testing.
A728 EX DE,HL Switch the slot pointer into HL.
A729 LD BC,$000C Point HL at the explode flag.
A72C ADD HL,BC
A72D SET 0,(HL) Set bit 0 of the explode flag.
A72F CALL ClearMaskScratch Call ClearMaskScratch.
A732 LD (IX+$00),$00 Write 00 to the shot type.
A736 POP HL Discard the stacked return addresses and saved registers.
A737 POP HL
A738 POP HL
A739 POP HL
A73A POP HL
A73B RET Return.
Prev: A53A Up: Map Next: A73C