| Technician Ted | Routines |
| Prev: AA49 | Up: Map | Next: ADBE |
|
Move memory buffers into the correct place
|
||||
| AA65 | LD SP,$5BFF | Put the stack somewhere safe | ||
| AA68 | LD HL,$8AC0 | Work out the size of what to copy based on the current location of the theme tune data | ||
| AA6B | LD DE,($A475) | |||
| AA6F | AND A | |||
| AA70 | SBC HL,DE | |||
| AA72 | LD B,H | |||
| AA73 | LD C,L | |||
| AA74 | LD HL,$A464 | First address to move (to make space for game status data) | ||
| AA77 | LD DE,$7AFF | Target address | ||
| AA7A | LDDR | Move it | ||
| AA7C | LD A,$01 | Select screen 2 | ||
| AA7E | LD ($A45B),A | |||
|
Display the title screen
|
||||
| AA81 | LD A,$09 | Blue border | ||
| AA83 | LD ($A421),A | |||
| AA86 | LD HL,($A475) | Get the location just past end of main screen | ||
| AA89 | LD DE,$F040 | Minus FC0 bytes to find the start | ||
| AA8C | ADD HL,DE | |||
| AA8D | LD DE,$4000 | Copy to start of screen | ||
| AA90 | LD B,$C0 | Number of lines to copy | ||
| AA92 | LD A,B | Remember these | ||
| AA93 | PUSH BC | |||
| AA94 | PUSH DE | |||
| AA95 | LD BC,$0020 | Number of characters to copy on this line | ||
| AA98 | CP $61 | Have we got to the bottom section yet? | ||
| AA9A | JR C,$AAA5 | Yes, move forward | ||
| AA9C | LD B,$1E | On the top half of the screen, everything but the right two characters is blank | ||
| AA9E | XOR A | |||
| AA9F | LD (DE),A | |||
| AAA0 | INC E | |||
| AAA1 | DJNZ $AA9F | |||
| AAA3 | LD C,$02 | Copy the last two actual characters | ||
| AAA5 | LDIR | Do the copy | ||
| AAA7 | POP DE | Restore | ||
| AAA8 | INC D | Next line | ||
| AAA9 | LD A,D | Done all the lines? | ||
| AAAA | AND $07 | |||
| AAAC | JR NZ,$AAB8 | Yes, move on | ||
| AAAE | LD A,E | Recalculate next line | ||
| AAAF | ADD A,$20 | |||
| AAB1 | LD E,A | |||
| AAB2 | JR C,$AAB8 | Move on if there are no more lines | ||
| AAB4 | LD A,D | Calculate next screen address | ||
| AAB5 | SUB $08 | |||
| AAB7 | LD D,A | |||
| AAB8 | POP BC | Restore | ||
| AAB9 | DJNZ $AA92 | Loop if there are more lines to copy | ||
| AABB | LD BC,$0300 | Copy the attributes | ||
| AABE | LDIR | |||
| AAC0 | LD A,$05 | |||
| AAC2 | LD ($A425),A | |||
| AAC5 | LD DE,$A85C | Copy the title screen UDG to screen 2 | ||
| AAC8 | LD HL,$9000 | |||
| AACB | LD ($A426),HL | |||
| AACE | LD C,$FF | |||
| AAD0 | CALL $B763 | |||
| AAD3 | CALL $B74A | Copy title text to screen 2 | ||
| AAD6 | LD A,$0E | Wait for ENTER or H to be pressed | ||
| AAD8 | LD ($A448),A | |||
| AADB | LD A,$01 | |||
| AADD | LD ($A400),A | |||
| AAE0 | LD HL,$A8C9 | |||
| AAE3 | LD ($A455),HL | |||
| AAE6 | LD HL,$5800 | |||
| AAE9 | LD ($A457),HL | |||
| AAEC | CALL $C1C0 | Display the title screen | ||
| AAEF | EX AF,AF' | Restore flags | ||
| AAF0 | JR Z,$AA86 | Loop back if end of sequence reached | ||
| AAF2 | RRA | Get the carry flag | ||
| AAF3 | JR C,$AB4C | Move ahead if we're starting the game | ||
|
Display instructions
|
||||
| AAF5 | PUSH DE | Store this | ||
| AAF6 | LD HL,$4000 | Clear the display file | ||
| AAF9 | LD DE,$4001 | |||
| AAFC | LD BC,$17FF | |||
| AAFF | LD (HL),$00 | |||
| AB01 | LDIR | |||
| AB03 | INC HL | Onto the attributes | ||
| AB04 | INC DE | |||
| AB05 | LD (HL),$07 | Fill with white paper / blank ink | ||
| AB07 | LD BC,$02FF | |||
| AB0A | LDIR | |||
| AB0C | LD DE,$A95A | Pointer to instruction text | ||
| AB0F | LD HL,$4000 | Start of display file | ||
| AB12 | LD A,(DE) | Get the next character | ||
| AB13 | CP $20 | Is this a printable character? ( > 20 ) | ||
| AB15 | JR NC,$AB22 | Jump forward if it is | ||
| AB17 | AND A | Is this the null terminating character? | ||
| AB18 | JR Z,$AB33 | Jump forward if it is | ||
| AB1A | XOR L | Skip to new line | ||
| AB1B | AND $1F | |||
| AB1D | XOR L | |||
| AB1E | LD L,A | |||
| AB1F | INC DE | Next character | ||
| AB20 | JR $AB12 | |||
| AB22 | CALL $B74A | Print the character | ||
| AB25 | LD A,L | Continue if we've not hit the end of this third of the screen | ||
| AB26 | AND $E0 | |||
| AB28 | ADD A,$20 | |||
| AB2A | LD L,A | |||
| AB2B | JR NC,$AB12 | |||
| AB2D | LD A,H | Move to next third of the screen | ||
| AB2E | ADD A,$08 | |||
| AB30 | LD H,A | |||
| AB31 | JR $AB12 | |||
| AB33 | POP DE | Restore DE | ||
| AB34 | LD A,$1E | |||
| AB36 | LD ($A448),A | |||
| AB39 | LD A,$01 | |||
| AB3B | LD ($A400),A | |||
| AB3E | LD HL,$A959 | Set next command to exit on keypress | ||
| AB41 | LD ($A455),HL | |||
| AB44 | DI | Turn off interrupts - using the game's system instead | ||
| AB45 | CALL $C05C | Yield to the game's interrupt handler | ||
| AB48 | EX AF,AF' | Restore flags | ||
| AB49 | JR Z,$AAEC | If tune finished, go back to the title sequence | ||
| AB4B | EI | Interrupts back on | ||
|
Start a new game
|
||||
| AB4C | LD HL,$5000 | Blank the bottom third of the screen | ||
| AB4F | LD DE,$5001 | |||
| AB52 | LD BC,$07FF | |||
| AB55 | LD (HL),$00 | |||
| AB57 | LDIR | |||
| AB59 | LD A,$80 | |||
| AB5B | LD ($A42B),A | |||
| AB5E | XOR A | |||
| AB5F | LD ($A42C),A | Full set of lives | ||
| AB62 | LD ($A45E),A | No tasks completed | ||
| AB65 | LD ($A437),A | |||
| AB68 | LD ($A439),A | Not dead | ||
| AB6B | LD ($A43A),A | Not visited any previous room | ||
| AB6E | LD ($A43B),A | |||
| AB71 | LD A,$01 | Tick once on every frame | ||
| AB73 | LD ($A440),A | |||
| AB76 | LD C,$05 | Set time to 08:30 | ||
| AB78 | LD DE,$A425 | |||
| AB7B | LD HL,$A8B7 | |||
| AB7E | LDIR | |||
| AB80 | LD HL,$A45B | Set tune on | ||
| AB83 | LD A,(HL) | |||
| AB84 | AND $01 | |||
| AB86 | LD (HL),A | |||
|
Detect a Kempston joystick
|
||||
| AB87 | LD BC,$001F | Port 31 for Kempston | ||
| AB8A | XOR A | Check for any bits set | ||
| AB8B | IN D,(C) | Read it | ||
| AB8D | OR D | Set zero flag if nothing read | ||
| AB8E | DJNZ $AB8B | Try 256 times to read a port | ||
| AB90 | AND $20 | Did we get a read on bit 5? | ||
| AB92 | JR NZ,$AB96 | No, keyboard only | ||
| AB94 | SET 5,(HL) | Set Kempston active | ||
|
Initialize game flags
|
||||
| AB96 | XOR A | |||
| AB97 | LD ($A438),A | Tick counter to 0 | ||
| AB9A | LD ($A40E),A | On the ground | ||
| AB9D | LD ($A403),A | |||
| ABA0 | LD ($A422),A | Move to The Factory Gates | ||
| ABA3 | LD HL,$88AC | Put Ted at the starting position | ||
| ABA6 | LD ($A406),HL | |||
| ABA9 | LD HL,$A57B | Put Ted facing right | ||
| ABAC | LD ($A408),HL | |||
| ABAF | LD HL,$00E0 | Set the default frame | ||
| ABB2 | LD ($A40A),HL | |||
| ABB5 | LD HL,$010D | |||
| ABB8 | LD ($A40C),HL | |||
| ABBB | LD A,$01 | |||
| ABBD | LD ($A40F),A | |||
| ABC0 | LD HL,$0000 | |||
| ABC3 | LD ($A44B),HL | |||
| ABC6 | LD HL,($A477) | Set theme tune to be in the in-game one | ||
| ABC9 | LD ($A451),HL | |||
| ABCC | LD A,$01 | |||
| ABCE | LD ($A450),A | |||
| ABD1 | LD HL,$AA23 | |||
| ABD4 | LD ($A459),HL | |||
| ABD7 | LD HL,($A46D) | Point to default room flags | ||
| ABDA | LD DE,$7DC0 | Copy to working store at 7DC0 | ||
| ABDD | LD IX,$AA53 | Point to offset table | ||
| ABE1 | LD B,$31 | Number of rooms | ||
| ABE3 | LD A,(HL) | Get the entry | ||
| ABE4 | SUB (IX+$00) | Subtract the offset | ||
| ABE7 | LD (DE),A | Set the copy in the working store | ||
| ABE8 | INC HL | Next room | ||
| ABE9 | INC DE | |||
| ABEA | LD A,(IX+$00) | Next entry | ||
| ABED | INC IX | |||
| ABEF | CP $DC | Have we reached the end of the offset table? | ||
| ABF1 | JR NZ,$ABF7 | No, skip this | ||
| ABF3 | LD IX,$AA49 | If we reached the end of the decryption table, loop back to the beginning | ||
| ABF7 | DJNZ $ABE3 | Loop back if more to do | ||
|
Main game loop starts here
|
||||
| ABF9 | XOR A | |||
| ABFA | LD ($A436),A | |||
| ABFD | CALL $AE77 | Set up the room data | ||
| AC00 | LD A,($A45B) | |||
| AC03 | BIT 3,A | |||
| AC05 | LD A,$00 | |||
| AC07 | JR NZ,$AC0F | |||
| AC09 | LD ($A42E),A | First frame of conveyor belt graphics | ||
| AC0C | LD ($A42F),A | |||
| AC0F | LD ($5C78),A | Set the FRAMES system variable | ||
| AC12 | LD HL,$A403 | Copy current flags over to the "last visited" copy | ||
| AC15 | LD DE,$A410 | |||
| AC18 | LD BC,$000D | |||
| AC1B | LDIR | |||
| AC1D | LD HL,$A439 | Get game flags | ||
| AC20 | LD A,(HL) | |||
| AC21 | AND $E6 | Turn off bits 0, 3 and 4 | ||
| AC23 | LD (HL),A | Store this | ||
| AC24 | LD HL,($A40A) | Get Ted's graphic offset | ||
| AC27 | LD DE,($A408) | Get graphic set | ||
| AC2B | ADD HL,DE | Combine to get graphic frame | ||
| AC2C | EX DE,HL | Put this in DE | ||
| AC2D | LD HL,($A406) | Put current screen address for Ted in HL | ||
| AC30 | LD A,($A40F) | |||
| AC33 | LD C,A | |||
| AC34 | CALL $B9EF | Set up moving objects and check collision detection | ||
| AC37 | CALL $AF5D | Enter the room and play until we leave it | ||
| AC3A | JR C,$ACB2 | Jump forward if we left by losing a life | ||
|
Move to another room
|
||||
| AC3C | BIT 7,A | Did we leave the room by walking out of it? | ||
| AC3E | JP NZ,$AD56 | Jump if not | ||
| AC41 | LD HL,($A422) | Get current room | ||
| AC44 | LD H,$00 | Set HL and DE to be offsets in the next rooms table | ||
| AC46 | LD E,L | |||
| AC47 | LD D,H | |||
| AC48 | ADD HL,HL | |||
| AC49 | ADD HL,HL | |||
| AC4A | LD BC,($A46F) | Add the base of the next rooms table | ||
| AC4E | ADD HL,BC | |||
| AC4F | LD C,A | Add offset for the direction | ||
| AC50 | LD B,$00 | |||
| AC52 | ADD HL,BC | |||
| AC53 | LD A,($A422) | Are we in the lift? | ||
| AC56 | CP $2A | |||
| AC58 | JR NZ,$AC65 | Jump if we're not | ||
| AC5A | LD A,($A43A) | Were we previously in the Forgotten Room? | ||
| AC5D | CP $2B | |||
| AC5F | JR NZ,$AC73 | Jump if we weren't | ||
| AC61 | LD A,$0F | |||
| AC63 | JR $AC73 | |||
| AC65 | LD ($A43A),A | Set last visited room to this one | ||
| AC68 | LD A,(HL) | Get the appropriate next room entry | ||
| AC69 | SRL E | Divide by 4 | ||
| AC6B | SRL E | |||
| AC6D | LD HL,$AA4A | Point to the offset table | ||
| AC70 | ADD HL,DE | Add the offset | ||
| AC71 | ADD HL,BC | Add the direction | ||
| AC72 | ADD A,(HL) | Add this to the basic value in the next room table to give us the next room | ||
| AC73 | LD ($A422),A | Store next room | ||
| AC76 | CP $30 | Is this the final room? | ||
| AC78 | JP Z,$AD2B | Move forward if it is | ||
| AC7B | BIT 0,C | Was the room entered by jumping or falling? | ||
| AC7D | JR NZ,$AC89 | No, move on | ||
| AC7F | LD A,($A406) | |||
| AC82 | XOR $1E | |||
| AC84 | LD ($A406),A | |||
| AC87 | JR $ACA4 | |||
| AC89 | XOR A | |||
| AC8A | BIT 1,C | |||
| AC8C | JR NZ,$AC93 | |||
| AC8E | LD ($A403),A | |||
| AC91 | LD A,$A0 | |||
| AC93 | LD HL,($A406) | |||
| AC96 | XOR L | |||
| AC97 | AND $E0 | |||
| AC99 | XOR L | |||
| AC9A | LD L,A | |||
| AC9B | LD A,H | |||
| AC9C | AND $F8 | |||
| AC9E | XOR $08 | |||
| ACA0 | LD H,A | |||
| ACA1 | LD ($A406),HL | |||
| ACA4 | LD HL,$A45B | |||
| ACA7 | RES 4,(HL) | |||
| ACA9 | BIT 3,(HL) | |||
| ACAB | JR Z,$ACAF | |||
| ACAD | SET 4,(HL) | |||
| ACAF | JP $ABF9 | Jump back round to play the next room | ||
|
Lost a life - flash the screen and restart the room
|
||||
| ACB2 | LD A,($A42D) | |||
| ACB5 | ADD A,$08 | |||
| ACB7 | LD C,A | |||
| ACB8 | CALL $BF35 | Invert the screen | ||
| ACBB | LD IX,$A8C1 | Point to "killed" sound data | ||
| ACBF | LD L,(IX+$00) | |||
| ACC2 | LD H,$00 | |||
| ACC4 | LD B,$0A | |||
| ACC6 | PUSH BC | |||
| ACC7 | CALL $BEF6 | Play it | ||
| ACCA | POP BC | |||
| ACCB | AND A | |||
| ACCC | LD HL,$AD51 | |||
| ACCF | PUSH HL | Remember HL as the next call uses it | ||
| ACD0 | CALL $B0DC | Flash the screen | ||
| ACD3 | POP HL | Restore it | ||
| ACD4 | INC IX | |||
| ACD6 | LD A,($A42D) | |||
| ACD9 | CP C | |||
| ACDA | JR NZ,$ACBF | |||
| ACDC | CALL $BF35 | Invert the screen (back to normal) | ||
| ACDF | LD A,($A42C) | |||
| ACE2 | INC A | |||
| ACE3 | LD ($A42C),A | |||
| ACE6 | ADD A,$7F | |||
| ACE8 | LD L,A | |||
| ACE9 | LD H,$5A | |||
| ACEB | LD A,($A45D) | |||
| ACEE | LD (HL),A | |||
| ACEF | LD HL,$A439 | Get flags | ||
| ACF2 | BIT 0,(HL) | Has Ted entered the room safely? | ||
| ACF4 | JR NZ,$AD05 | Move forward if so | ||
| ACF6 | BIT 1,(HL) | Has Ted entered the room and died without hitting a safe spot? | ||
| ACF8 | JR Z,$AD03 | Move forward if so | ||
| ACFA | LD A,$28 | Pause for a bit | ||
| ACFC | DJNZ $ACFC | |||
| ACFE | DEC A | |||
| ACFF | JR NZ,$ACFC | |||
| AD01 | JR $ACB2 | Back round to lose another life | ||
| AD03 | SET 1,(HL) | Ted died when entering the room without hitting a safe spot, set "infinite death" flag | ||
| AD05 | LD HL,$A410 | Copy flags from the last room into the current one | ||
| AD08 | LD DE,$A403 | |||
| AD0B | LD BC,$000D | |||
| AD0E | LDIR | |||
| AD10 | LD HL,$A45B | |||
| AD13 | BIT 3,(HL) | |||
| AD15 | RES 3,(HL) | |||
| AD17 | SET 4,(HL) | |||
| AD19 | JR Z,$AD28 | |||
| AD1B | RES 4,(HL) | |||
| AD1D | LD HL,($A463) | |||
| AD20 | LD A,H | |||
| AD21 | LD H,$00 | |||
| AD23 | LD DE,$7DC0 | |||
| AD26 | ADD HL,DE | |||
| AD27 | LD (HL),A | |||
| AD28 | JP $ABF9 | Back round to main loop | ||
| AD2B | LD A,($A45E) | Have we completed all 21 tasks? | ||
| AD2E | CP $15 | |||
| AD30 | JR NZ,$AD56 | No, so jump forward to the "Game over" routine | ||
| AD32 | LD HL,$7DC0 | Point to the room flags table | ||
| AD35 | XOR A | Set A to 0 to check against room flags | ||
| AD36 | LD B,$31 | Iterate through all rooms | ||
| AD38 | OR (HL) | Test for any flags set - this will be reflected in A | ||
| AD39 | INC HL | Next room | ||
| AD3A | DJNZ $AD38 | Repeat until all rooms checked | ||
| AD3C | RLA | Was bit 8 set? | ||
| AD3D | JR C,$AD56 | Yes, a room wasn't completed properly, so jump to "Game over" | ||
| AD3F | CALL $AE28 | Ted has reached the last room with all tasks done - game won! | ||
| AD42 | LD HL,$88BE | |||
| AD45 | LD DE,$A813 | |||
| AD48 | LD BC,$010D | |||
| AD4B | LD IX,$A825 | |||
| AD4F | JR $AD66 | |||
|
Run out of lives
|
||||
| AD51 | LD A,$20 | |||
| AD53 | LD ($A42C),A | |||
| AD56 | CALL $AE4E | Set up movement data for the final sequence and put Ted in position | ||
| AD59 | LD HL,$887D | New screen address of Ted | ||
| AD5C | LD DE,$A7BD | Point DE to the "game over" automatic movement table | ||
| AD5F | LD BC,$00AD | Sound to play while Ted is in mid-air | ||
| AD62 | LD IX,$A7FD | |||
| AD66 | LD ($A406),HL | Set new screen address | ||
| AD69 | LD ($A404),DE | Set new movement table | ||
| AD6D | LD ($A40C),BC | Set moving sound | ||
| AD71 | LD ($A43D),IX | |||
| AD75 | LD HL,$0000 | |||
| AD78 | LD ($A40A),HL | |||
| AD7B | LD HL,$A47B | |||
| AD7E | LD ($A408),HL | |||
| AD81 | LD A,$FF | |||
| AD83 | LD ($A40F),A | |||
| AD86 | LD A,(IX-$01) | |||
| AD89 | LD ($A43C),A | |||
| AD8C | LD A,$30 | Move straight to the final room | ||
| AD8E | LD ($A422),A | |||
| AD91 | LD HL,$A45B | |||
| AD94 | SET 4,(HL) | |||
| AD96 | CALL $AE77 | Enter the final room | ||
| AD99 | CALL $BECF | |||
| AD9C | XOR A | |||
| AD9D | LD ($A42F),A | |||
| ADA0 | LD ($A440),A | |||
| ADA3 | LD ($5C78),A | Set FRAMES to 0 | ||
| ADA6 | LD ($A43F),A | |||
| ADA9 | LD ($A403),A | |||
| ADAC | LD HL,$A439 | Get flags | ||
| ADAF | SET 2,(HL) | Turn on "automatic movement" mode | ||
| ADB1 | CALL $AF5D | Enter the room and run the final sequence | ||
| ADB4 | LD HL,($7ED0) | |||
| ADB7 | LD A,H | |||
| ADB8 | OR L | |||
| ADB9 | JR Z,$AD42 | |||
| ADBB | JP $AA81 | Jump back to the title screen | ||
| Prev: AA49 | Up: Map | Next: ADBE |