| 0000 | DI | |||
| 0001 | JMP IO_Init(4E37) | |||
| EasterEgg: | 4E31 | LD HL,5012 | Print "WRITTEN BY MICRO-SOFT..." |
| 4E34 | CALL 21A8 | ||
| IO_Init: | 4E37 | LD HL,521D | |
| 4E3A | LD SP,HL | ||
| 4E3B | LD (06E5),HL | ||
| 4E3E | LD (0AD3),HL | ||
| 4E41 | CALL 4D66 | ||
| 4E44 | LD HL,FFFF | ||
| 4E47 | LD (06E7),HL | ||
| 4E4A | XOR A | ||
| 4E4B | LD (06E4),A | ||
| 4E4E | CALL 17BD | ||
| 4E51 | LD (0A8B),A | ||
| 4E54 | LD (06D7),A | ||
| 4E57 | INC HL | ||
| 4E58 | LD (06D9),HL | ||
| 4E5B | LD (06DB),HL | ||
| 4E5E | LD (06DD),HL | ||
| 4E61 | LD HL,0AA0 | ||
| 4E64 | LD (0A9E),HL |
| 4E67 | LD HL,503B | Print "MEMORY SIZE" | |
| 4E6A | CALL 21A8 | ||
| 4E6D | CALL 0E36 | ||
| 4E70 | JP C,4E67 | ||
| 4E73 | RST 10H | ||
| 4E74 | CP 41 | If user enters 'A', jump back to show the Easter Egg. | |
| 4E76 | JP Z,EasterEgg(4E31) | ||
| 4E79 | OR A | If user provided an input, jump ahead. | |
| 4E7A | JP NZ,Mem_given(4E90) | ||
| User has given no input, so we have to find the top of usable RAM by writing as high as we can. | |||
| 4E7D | LD HL,51D7 | 51D7 is lowest address of non-BASIC RAM. | |
| TestMemByte: | 4E80 | INC HL | |
| 4E81 | LD A,H | If we've reached address 0000 then we've successfully tested the whole of addressable RAM (64K) so can jump to GotMem. | |
| 4E82 | OR L | ||
| 4E83 | JP Z,GotMem(4EA1) | ||
| 4E86 | LD A,(HL) | Read a byte. | |
| 4E87 | CPL | Invert it. | |
| 4E88 | LD (HL),A | Write it back. | |
| 4E89 | CP (HL) | Did it work? | |
| 4E8A | JP Z,TestMemByte(4E80) | If so, loop back. | |
| 4E8D | JP GotMem(4EA1) | ||
| User has specified number of Kilobytes(?check?). Not sure what's happening here. | |||
| Mem_given: | 4E90 | LD HL,0989 | poss. HL = input addr. |
| 4E93 | CALL 1C64 | poss. Convert input to integer (in DE). | |
| 4E96 | LD A,(HL) | ||
| 4E97 | OR A | ||
| 4E98 | JP NZ,0BC3 | poss. Jump to "SYNTAX ERROR". | |
| 4E9B | LD A,D | ||
| 4E9C | OR A | ||
| 4E9D | JP Z,14DF | ||
| 4EA0 | EX DE,HL | ||
| At this point HL holds the address of the last byte of usable RAM, +1. | |||
| GotMem: | 4EA1 | DEC HL | HL = address of last byte of usable RAM. |
| 4EA2 | PUSH HL | ||
| 4EA3 | LD DE,FF9D | DE = -99. | |
| 4EA6 | POP HL | ||
| 4EA7 | DEC HL | HL = address of last word of usable RAM. | |
| 4EA8 | LD (0A9C),HL | Store last_word somewhere. | |
| 4EAB | ADD HL,DE | HL = HL - 99. | |
| 4EAC | JP NC,0B9D | Spong! Inconceivable jump surely?... | |
| 4EAF | DEC HL | HL = last_word - 100. | |
| 4EB0 | PUSH HL | Keep it on the stack. | |
| 4EB1 | LD A,84 | No idea what this bit is for... | |
| 4EB3 | LD (06DF),A | ||
| 4EB6 | LD A,70 | ||
| 4EB8 | LD (06E0),A | ||
| 4EBB | LD HL,4F07 | Print "LINEPRINTER" | |
| 4EBE | CALL 21A8 | ||
| 4EC1 | CALL 0E36 | ||
| 4EC4 | JP C,4EBB | ||
| 4EC7 | RST 10H | ||
| 4EC8 | CP 51 | A='Q'? | |
| 4ECA | JP Z,PrinterQ(4F13) | ||
| 4ECD | CP 43 | A='C'? | |
| 4ECF | JP Z,PrinterC(4EED) | ||
| 4ED2 | CP 4F | A='O'? | |
| 4ED4 | JP NZ,4EBB | Jump back cos no valid answer given. | |
| PrinterO: | 4ED7 | LD DE,512A | DE = address of PrinterDriver_O. |
| 4EDA | LD C,AE | C = size of PrinterDriver_O. | |
| 4EDC | LD A,01 | ||
| 4EDE | OUT (02),A | ||
| 4EE0 | LD A,50 | ||
| 4EE2 | LD (06DF),A | ||
| 4EE5 | LD A,38 | ||
| 4EE7 | LD (06E0),A | ||
| 4EEA | JP CopyDriver(4EF9) | ||
| PrinterC: | 4EED | LD DE,50A2 | DE = address of PrinterDriver_C. |
| 4EF0 | LD C,89 | C = size of PrinterDriver_C. | |
| 4EF2 | LD A,11 | ||
| 4EF4 | OUT (03),A | ||
| 4EF6 | XOR A | ||
| 4EF7 | OUT (02),A | ||
| Here we copy the 'driver' for the given printer into place, much as modern OS'es load printer drivers today. The source for both printer drivers is right up in memory and it is safe to assume it will be reused for applications. | |||
| CopyDriver: | 4EF9 | LD HL,3C2D | HL = address of PrinterDriver |
| 4EFC | LD A,(DE) | ||
| 4EFD | LD (HL),A | ||
| 4EFE | INC HL | ||
| 4EFF | INC DE | ||
| 4F00 | DEC C | ||
| 4F01 | JP NZ,4EFC | ||
| 4F04 | JP HighestDisk(4F38) | ||
| 4F07 | "LINEPRINTER\0" | ||
| PrinterQ: | 4F13 | XOR A | |
| 4F14 | OUT (30),A | ||
| 4F16 | OUT (32),A | ||
| 4F18 | OUT (34),A | ||
| 4F1A | OUT (36),A | ||
| 4F1C | OUT (35),A | ||
| 4F1E | LD A,FF | ||
| 4F20 | OUT (31),A | ||
| 4F22 | OUT (33),A | ||
| 4F24 | OUT (37),A | ||
| 4F26 | LD A,04 | ||
| 4F28 | OUT (30),A | ||
| 4F2A | OUT (32),A | ||
| 4F2C | OUT (34),A | ||
| 4F2E | OUT (36),A | ||
| 4F30 | LD A,FC | ||
| 4F32 | OUT (37),A | ||
| 4F34 | LD A,FA | ||
| 4F36 | OUT (37),A | ||
| HighestDisk: | 4F38 | LD HL,4FBB | Print "HIGHEST DISK NUMBER" and get input. |
| 4F3B | CALL 4FF5 | ||
| 4F3E | LD (0786),A | ||
| 4F41 | LD HL,4E2F | HL=0x4E2F + 0x27 * (highest_disk_number + 1). | |
| 4F44 | LD DE,0027 | ||
| 4F47 | INC A | ||
| 4F48 | ADD HL,DE | ||
| 4F49 | DEC A | ||
| 4F4A | JP NZ,4F48 |
| 4F4D | PUSH HL | Preserve highest_disk. | |
| 4F4E | LD HL,4FCF | Print "HOW MANY FILES" and get input. | |
| 4F51 | CALL 4FF5 | ||
| 4F54 | POP HL | HL = highest_disk. | |
| 4F55 | LD (0827),HL | Store it somewhere. | |
| 4F58 | LD DE,0829 | ||
| 4F5B | LD (0849),A | Store file_count somewhere | |
| I think we're initialising a file table here: A table of file_count+1 entries, each entry | |||
| 4F5E | INC A | ||
| 4F5F | LD BC,008A | BC=0x8A, poss. file descriptor size? | |
| 4F62 | EX DE,HL | ||
| 4F63 | LD (HL),E | ||
| 4F64 | INC HL | ||
| 4F65 | LD (HL),D | ||
| 4F66 | INC HL | ||
| 4F67 | EX DE,HL | ||
| 4F68 | ADD HL,BC | ||
| 4F69 | DEC A | ||
| 4F6A | JP NZ,4F62 | ||
| 4F6D | LD (0813),HL | ||
| 4F70 | LD HL,4FDE | Print "HOW MANY RANDOM FILES" and get input. | ||
| 4F73 | CALL 4FF5 | |||
| 4F76 | LD (0812),A | |||
| 4F79 | OR A | |||
| 4F7A | INC A | |||
| 4F7B | CALL 30C0 | |||
| 4F7E | INC HL | |||
| 4F7F | LD (06E9),HL | |||
| 4F82 | EX (SP),HL | HL=HIMEM | ||
| 4F83 | LD DE,521D | If HIMEM < 0x521D then jump to "OUT OF MEMORY" error. | ||
| 4F86 | RST 20H | |||
| 4F87 | JP C,0B9D | |||
| 4F8A | POP DE | DE = rand_file | ||
| 4F8B | LD SP,HL | SP = HIMEM. | ||
| 4F8C | LD (06E5),HL | |||
| 4F8F | LD (0AD3),HL | |||
| 4F92 | EX DE,HL | |||
| 4F93 | CALL 0B8E | This func. seems to check that there is enough stack space. | ||
| 4F96 | LD A,E | HL = DE - HL | ||
| 4F97 | SUB L | |||
| 4F98 | LD L,A | |||
| 4F99 | LD A,D | |||
| 4F9A | SBC H | |||
| 4F9B | LD H,A | |||
| 4F9C | LD BC,FFF0 | HL = HL - 0x10. | ||
| 4F9F | ADD HL,BC | |||
| 4FA0 | CALL 17BD | |||
| 4FA3 | CALL 4661 | |||
| 4FA6 | LD HL,5047 | |||
| 4FA9 | CALL 21A8 | |||
| 4FAC | LD HL,21A8 | |||
| 4FAF | LD (0C63),HL | |||
| 4FB2 | LD HL,0BA2 | |||
| 4FB5 | LD (0002),HL | |||
| 4FB8 | JP 4D4C | |||
| 4FBB | "HIGHEST DISK NUMBER\0" | |||
| 4FCF | "HOW MANY FILES\0" | |||
| 4FDE | "HOW MANY RANDOM FILES\0" | |||
| 4FF4 | POP HL | |||
| 4FF5 | PUSH HL | |||
| 4FF6 | CALL 21A8 | |||
| 4FF9 | CALL 0E36 | |||
| 4FFC | JP C,4FF4 | |||
| 4FFF | RST 10H | |||
| 5000 | CALL 1C64 | |||
| 5003 | DEC HL | |||
| 5004 | RST 10H | |||
| 5005 | JP NZ,4FF4 | |||
| 5008 | LD HL,000F | |||
| 500B | RST 20H | |||
| 500C | JP C,4FF4 | |||
| 500F | POP AF | |||
| 5010 | LD A,E | |||
| 5011 | RET | |||
| 5012 | "\r\n\nWRITTEN FOR ROYALTIES BY MICRO-SOFT\r\n\0" | |||
| 503B | "MEMORY SIZE\0" | |||
| 5047 | " BYTES FREE\r\nALTAIR BASIC REV. 4.1\r\n[DISK EXTENDED VERSION]\r\nCOPYRIGHT 1977 BY MITS INC.\r\n\0" | |||
| 50A2 - 5129 | Source for PrinterDriver_C | |||
| 512A - 51?? | Source for PrinterDriver_O | |||