Prev: 89A7 Up: Map Next: 8C05
89D3: Spawn Enemy
Used by the routine at UpdateEnemySpawning.
Starts an enemy in the slot found by FindFreeSlot. The kind of enemy comes from the table at EnemySpawnTable, indexed by a counter that steps through a sequence of values.
Input
IX Address of the free slot
SpawnEnemy 89D3 LD B,$06 Use a counter limit of six...
89D5 LD A,($F5F1) ...or eight if the flags at F5F1 and F5F2 are both set.
89D8 AND A
89D9 JR Z,SpawnEnemy_Counter
89DB LD A,($F5F2)
89DE AND A
89DF JR Z,SpawnEnemy_Counter
89E1 LD B,$08
SpawnEnemy_Counter 89E3 LD A,($9932) Fetch the counter from EnemySpawnCounter.
89E6 INC A Increase it and store it.
89E7 LD ($9932),A
89EA CP B Compare it with the limit.
89EB JR C,SpawnEnemy_Kind Jump to SpawnEnemy_Kind if it is lower.
89ED XOR A Otherwise restart the counter at zero.
89EE LD ($9932),A
SpawnEnemy_Kind 89F1 CP $04 Jump to SpawnEnemy_Store if the counter is not four.
89F3 JR NZ,SpawnEnemy_Store
89F5 LD B,A Keep the counter in B.
89F6 LD A,R Fetch a pseudo-random value from the refresh register.
89F8 AND %00110010 Keep some of its bits.
89FA LD A,B Restore the counter.
89FB JR Z,SpawnEnemy_Store Jump to SpawnEnemy_Store if the random bits were zero.
89FD DEC A Otherwise use three instead of four.
SpawnEnemy_Store 89FE LD ($89D2),A Store the kind of enemy in 89D2.
8A01 CP $01 Jump to SpawnEnemy_CheckZone if it is one.
8A03 JR Z,SpawnEnemy_CheckZone
8A05 CP $05 Jump to SpawnEnemy_CheckBonus if it is not five.
8A07 JR NZ,SpawnEnemy_CheckBonus
SpawnEnemy_CheckZone 8A09 LD A,($CE58) Fetch the map zone from CE58.
8A0C CP $03 Jump to SpawnEnemy_Reset if it is lower than 03.
8A0E JR C,SpawnEnemy_Reset
8A10 CP $0A Jump to SpawnEnemy_CheckBonus if it is lower than 0A.
8A12 JR C,SpawnEnemy_CheckBonus
SpawnEnemy_Reset 8A14 XOR A Use kind zero instead.
8A15 LD ($89D2),A
SpawnEnemy_CheckBonus 8A18 LD A,($CE58) Fetch the map zone from CE58.
8A1B CP $0B Jump to SpawnEnemy_Limit if it is 0B or more.
8A1D JR NC,SpawnEnemy_Limit
8A1F LD A,($87F5) Fetch the bonus timer from 87F5.
8A22 AND A Test it.
8A23 JP NZ,SpawnEnemy_Bonus Jump to SpawnEnemy_Bonus if it is running.
SpawnEnemy_Limit 8A26 LD B,$03 B=03.
This entry point is used by the routine at SpawnSpecialEnemy.
SpawnEnemy_ChooseSide 8A28 LD C,$00 Clear C.
8A2A LD A,($C8FE) Fetch the first byte of C8FE.
8A2D AND A Test it.
8A2E JR Z,SpawnEnemy_ChooseLower Jump to SpawnEnemy_ChooseLower if it is zero.
8A30 INC A Increment it.
8A31 JR Z,SpawnEnemy_ChooseLower Jump to SpawnEnemy_ChooseLower if it was FF.
8A33 LD A,($CCBB) Fetch the scroll speed from HorizontalSpeed.
8A36 BIT 7,A Jump to SpawnEnemy_ChooseRight if bit 7 is set.
8A38 JR NZ,SpawnEnemy_ChooseRight
8A3A LD A,B Keep only bit 0 of B.
8A3B AND $01
8A3D LD B,A
8A3E JR SpawnEnemy_ChooseLower Jump to SpawnEnemy_ChooseLower.
SpawnEnemy_ChooseRight 8A40 LD C,$02 C=02.
SpawnEnemy_ChooseLower 8A42 LD A,($C900) Fetch the first byte of C900.
8A45 AND A Test it.
8A46 JR Z,SpawnEnemy_Pick Jump to SpawnEnemy_Pick if it is zero.
8A48 INC A Increment it.
8A49 JR Z,SpawnEnemy_Pick Jump to SpawnEnemy_Pick if it was FF.
8A4B INC C Add one to C.
8A4C LD A,($CCBA) Fetch the scroll speed from VerticalSpeed.
8A4F BIT 7,A Jump to SpawnEnemy_Pick if bit 7 is set.
8A51 JR NZ,SpawnEnemy_Pick
8A53 DEC C Subtract one from C.
8A54 LD A,B Keep only bit 1 of B.
8A55 AND $02
8A57 LD B,A
SpawnEnemy_Pick 8A58 LD A,$04 Set the number of attempts in 8C04 to four.
8A5A LD ($8C04),A
8A5D LD A,($9BCB) Fetch the first byte of the random seed.
8A60 AND B Mask it with B and combine it with C.
8A61 OR C
SpawnEnemy_Try 8A62 LD ($5C1C),A Store the result in ScratchValue.
8A65 LD HL,$DC91 Use the table at VisibleTiles.
8A68 CALL AddAToHL Add a random value to the address.
8A6B LD E,(HL) Fetch the entry.
8A6C LD HL,$855C Use the table at SpawnPatternTable and add the entry.
8A6F ADD HL,DE
8A70 LD A,(HL) Fetch the pattern.
8A71 LD ($5C1D),A Store it in TileNumber.
8A74 LD A,R Fetch a pseudo-random value from the refresh register.
8A76 AND %00000111 Keep three bits.
8A78 LD ($5C1E),A Store them in ScratchPair.
8A7B ADD A,A Multiply them by eight...
8A7C ADD A,A
8A7D ADD A,A
8A7E ADD A,$47 ...and add 47 to make an attribute value.
8A80 LD ($8A8B),A Store it in the data at 8A8B.
8A83 XOR A Clear the bit counter in 5C1F.
8A84 LD ($5C1F),A
SpawnEnemy_Bit 8A87 LD A,($5C1D) Fetch the pattern from TileNumber.
8A8A RLC B Rotate the mask in B left.
8A8C JR NZ,SpawnEnemy_Position Jump to SpawnEnemy_Position if the bit was set.
8A8E LD A,($5C1D) Fetch the pattern again.
8A91 RRCA Rotate it right.
8A92 LD ($5C1D),A Store it.
8A95 LD A,($5C1F) Fetch the bit counter from 5C1F.
8A98 INC A Increment it and store it.
8A99 LD ($5C1F),A
8A9C CP $08 Jump back to SpawnEnemy_Bit if all eight bits have not been tried.
8A9E JR NZ,SpawnEnemy_Bit
8AA0 JP SpawnEnemy_Retry Give up and jump to SpawnEnemy_Retry.
SpawnEnemy_Position 8AA3 LD A,($5C1E) Fetch the random three bits from ScratchPair.
8AA6 LD B,A Add the bit counter from 5C1F.
8AA7 LD A,($5C1F)
8AAA ADD A,B
8AAB AND %00000111 Keep the bottom three bits.
8AAD ADD A,A Double it to index a pair of bytes.
8AAE LD HL,$8605 Use the table at SpawnPositionTable.
8AB1 CALL AddAToHL Add the offset to the address.
8AB4 LD A,(HL) Set the horizontal position of the enemy from the table.
8AB5 LD (IX+$02),A
8AB8 INC HL Set the vertical position of the enemy from the table.
8AB9 LD A,(HL)
8ABA LD (IX+$05),A
8ABD LD (IX+$0D),$FF Make the enemy's attribute FF.
8AC1 LD A,($9BCC) Fetch the second byte of the random seed.
8AC4 AND %01001000 Keep two bits.
8AC6 JR NZ,SpawnEnemy_FetchKind Jump to SpawnEnemy_FetchKind if either is set.
8AC8 LD (IX+$0D),$77 Otherwise make the attribute 77.
SpawnEnemy_FetchKind 8ACC LD A,($89D2) Fetch the kind of enemy from 89D2.
SpawnEnemy_SetKind 8ACF ADD A,A Multiply it by four.
8AD0 ADD A,A
8AD1 LD HL,$990A Use the table at EnemySpawnTable.
8AD4 CALL AddAToHL Add the offset to the address.
8AD7 CALL FreeObjectSlot Clear the slot.
8ADA LD (IX+$15),$01 Set the lifetime of the enemy to one.
8ADE LD A,(HL) Set the type of the enemy from the table.
8ADF LD (IX+$00),A
8AE2 INC HL
8AE3 LD A,(HL)
8AE4 LD (IX+$10),A Set the flags of the enemy from the table.
8AE7 INC HL
8AE8 LD A,(HL)
8AE9 LD (IX+$13),A Set the first state byte of the enemy from the table.
8AEC INC HL
8AED LD A,(HL)
8AEE LD (IX+$14),A Set the second state byte of the enemy from the table.
8AF1 LD A,(IX+$00) Fetch the type of the enemy.
8AF4 CP $1D Jump to SpawnEnemy_Type1D if it is 1D.
8AF6 JP Z,SpawnEnemy_Type1D
8AF9 LD HL,($CE57) Fetch the map position from MapPosition.
8AFC LD A,($5C1C) Fetch the value from ScratchValue.
8AFF AND A Test it.
8B00 JR Z,SpawnEnemy_Place Jump to SpawnEnemy_Place if it is zero.
8B02 BIT 0,A Jump to SpawnEnemy_Column if bit 0 is clear.
8B04 JR Z,SpawnEnemy_Column
8B06 INC H Move the enemy one zone along.
SpawnEnemy_Column 8B07 BIT 1,A Jump to SpawnEnemy_Place if bit 1 is clear.
8B09 JR Z,SpawnEnemy_Place
8B0B LD A,($DDF7) Fetch the column from NextColumn.
8B0E LD L,A Use it as the column of the enemy.
SpawnEnemy_Place 8B0F LD (IX+$01),L Set the map column of the enemy.
8B12 LD (IX+$04),H Set the map zone of the enemy.
8B15 LD A,(IX+$00) Fetch the type of the enemy.
8B18 CP $13 Jump to SpawnEnemy_Attribute if it is not 13.
8B1A JR NZ,SpawnEnemy_Attribute
8B1C LD (IX+$13),$00 Clear the first state byte of the enemy.
8B20 LD A,R Fetch a pseudo-random value from the refresh register.
8B22 AND %00011100 Keep some of its bits.
8B24 JR NZ,SpawnEnemy_Zone Jump to SpawnEnemy_Zone if any are set.
8B26 INC (IX+$13) Otherwise change the state of the enemy.
SpawnEnemy_Zone 8B29 LD A,H Fetch the map zone of the enemy.
8B2A CP $05 Jump to SpawnEnemy_Finish if it is 05 or higher.
8B2C JR NC,SpawnEnemy_Finish
8B2E LD (IX+$10),$23 Set the flags of the enemy to 23.
8B32 LD (IX+$04),$04 Set the map zone of the enemy to 04.
8B36 LD (IX+$05),$1F Set the vertical position of the enemy to 1F.
8B3A LD (IX+$0D),$FF Make the attribute of the enemy FF.
8B3E LD A,($DDF7) Fetch the column from NextColumn.
8B41 CP L Compare it with the column of the enemy.
8B42 JR Z,SpawnEnemy_SameColumn Jump to SpawnEnemy_SameColumn if it is the same.
8B44 LD A,($CE45) Fetch the horizontal position of the player from PositionAcross.
8B47 SUB $30 Subtract 30 from it.
8B49 JR C,SpawnEnemy_Remove Remove the enemy if that goes below zero.
8B4B ADD A,$08 Add 08 to it.
8B4D LD (IX+$02),A Set the horizontal position of the enemy.
8B50 RET Return.
SpawnEnemy_SameColumn 8B51 LD A,($CE45) Fetch the horizontal position of the player from PositionAcross.
8B54 LD (IX+$02),A Set the horizontal position of the enemy.
8B57 RET Return.
SpawnEnemy_Attribute 8B58 LD A,R Fetch a pseudo-random value from the refresh register.
8B5A AND %00000111 Keep three bits.
8B5C LD B,A Copy them into B.
8B5D LD A,H Fetch the map zone of the enemy.
8B5E CP $0C Jump to SpawnEnemy_Colour if it is 0C or higher.
8B60 JR NC,SpawnEnemy_Colour
8B62 CP $04 Jump to SpawnEnemy_Colour if it is lower than 04.
8B64 JR C,SpawnEnemy_Colour
8B66 LD A,B Keep only two bits of the random value.
8B67 AND $03
8B69 LD B,A
SpawnEnemy_Colour 8B6A LD A,B Fetch the random value.
8B6B LD HL,$9933 Use the table at EnemyAttributes.
8B6E CALL AddAToHL Add the value to the address.
8B71 LD A,(HL) Fetch the attribute from the table.
8B72 LD (IX+$0D),A Set the attribute of the enemy.
SpawnEnemy_Finish 8B75 CALL FindObjectScreenPosition Update the enemy.
8B78 BIT 7,(IX+$10) Jump to SpawnEnemy_Accelerate if bit 7 of the flags of the enemy is clear.
8B7C JR Z,SpawnEnemy_Accelerate
8B7E LD (IX+$00),$FF Otherwise remove the enemy.
SpawnEnemy_Retry 8B82 LD A,($8C04) Fetch the number of attempts left from 8C04.
8B85 DEC A Decrease it and store it.
8B86 LD ($8C04),A
8B89 RET Z Return if there are none left.
8B8A LD A,($5C1C) Fetch the value from ScratchValue.
8B8D INC A Move on to the next one...
8B8E AND %00000011 ...keeping two bits.
8B90 JP SpawnEnemy_Try Try again.
SpawnEnemy_Accelerate 8B93 JP AccelerateTowardsPlayer_Horizontal Set the acceleration of the enemy.
SpawnEnemy_Remove 8B96 LD (IX+$00),$FF Free the slot.
8B9A RET Return.
SpawnEnemy_Bonus 8B9B LD IY,$C8E5 Use the player's object at ShipObject.
8B9F CALL CopyPosition Copy the position of the player to the enemy.
8BA2 LD A,($9BCB) Fetch the first byte of the random seed.
8BA5 LD B,A Copy it into B.
8BA6 AND %00110000 Keep two bits.
8BA8 ADD A,$18 Add 18.
8BAA BIT 7,B Jump to SpawnEnemy_BonusSpeed if bit 7 of the random value is clear.
8BAC JR Z,SpawnEnemy_BonusSpeed
8BAE SUB $18 Subtract 18...
8BB0 NEG ...and negate the result.
SpawnEnemy_BonusSpeed 8BB2 LD (IX+$07),A Set the horizontal speed of the enemy.
8BB5 LD A,(IY+$1E) Fetch the second vertical value of the player.
8BB8 SUB $10 Subtract 10...
8BBA NEG ...and negate the result.
8BBC LD (IX+$09),A Set the vertical speed of the enemy.
8BBF CALL MoveObject Draw the enemy.
8BC2 LD A,($CE57) Fetch the map column from MapPosition.
8BC5 CP (IX+$01) Compare it with the map column of the enemy.
8BC8 LD A,$09 Select the kind of enemy.
8BCA JP Z,SpawnEnemy_SetKind Jump to SpawnEnemy_SetKind if they are the same.
8BCD DEC A Otherwise use the one before.
8BCE JP SpawnEnemy_SetKind Jump to SpawnEnemy_SetKind.
SpawnEnemy_Type1D 8BD1 LD A,($9BCB) Fetch the first byte of the random seed.
8BD4 AND %00001000 Keep bit 3.
8BD6 SRL A Shift it right twice.
8BD8 SRL A
8BDA ADD A,$02 Add two.
8BDC LD (IX+$09),A Set the vertical speed of the enemy.
8BDF LD A,($9BCC) Fetch the second byte of the random seed.
8BE2 AND %00001000 Keep bit 3.
8BE4 SRL A Shift it right twice.
8BE6 SRL A
8BE8 ADD A,$02 Add two.
8BEA LD (IX+$07),A Set the horizontal speed of the enemy.
8BED NEG Negate it and copy it into B.
8BEF LD B,A
8BF0 LD A,($CE57) Fetch the map column from MapPosition.
8BF3 CP (IX+$01) Compare it with the map column of the enemy.
8BF6 LD (IX+$0D),$FE Make the attribute of the enemy FE.
8BFA RET Z Return if they are the same.
8BFB LD (IX+$07),B Otherwise reverse the horizontal speed.
8BFE LD (IX+$0D),$EE Make the attribute of the enemy EE.
8C02 RET Return.
8C03 DEFB $00
8C04 DEFB $00
Prev: 89A7 Up: Map Next: 8C05