2. Initialization

Once BASIC has been loaded from disk, execution begins right at the bottom of memory.

2.1 Jump forward

A simple jump to the initialisation code.

0000DI
0001JMP IO_Init(4E37)


2.2 I/O Init

todo.

EasterEgg:4E31LD HL,5012Print "WRITTEN BY MICRO-SOFT..."
4E34CALL 21A8
IO_Init:4E37LD HL,521D
4E3ALD SP,HL
4E3BLD (06E5),HL
4E3ELD (0AD3),HL
4E41CALL 4D66
4E44LD HL,FFFF
4E47LD (06E7),HL
4E4AXOR A
4E4BLD (06E4),A
4E4ECALL 17BD
4E51LD (0A8B),A
4E54LD (06D7),A
4E57INC HL
4E58LD (06D9),HL
4E5BLD (06DB),HL
4E5ELD (06DD),HL
4E61LD HL,0AA0
4E64LD (0A9E),HL


2.3 "MEMORY SIZE? "

todo.

4E67LD HL,503BPrint "MEMORY SIZE"
4E6ACALL 21A8
4E6DCALL 0E36
4E70JP C,4E67
4E73RST 10H
4E74CP 41If user enters 'A', jump back to show the Easter Egg.
4E76JP Z,EasterEgg(4E31)
4E79OR AIf user provided an input, jump ahead.
4E7AJP 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.
4E7DLD HL,51D751D7 is lowest address of non-BASIC RAM.
TestMemByte:4E80INC HL
4E81LD A,HIf we've reached address 0000 then we've successfully tested the whole of addressable RAM (64K) so can jump to GotMem.
4E82OR L
4E83JP Z,GotMem(4EA1)
4E86LD A,(HL)Read a byte.
4E87CPLInvert it.
4E88LD (HL),AWrite it back.
4E89CP (HL)Did it work?
4E8AJP Z,TestMemByte(4E80)If so, loop back.
4E8DJP GotMem(4EA1)
User has specified number of Kilobytes(?check?). Not sure what's happening here.
Mem_given:4E90LD HL,0989poss. HL = input addr.
4E93CALL 1C64poss. Convert input to integer (in DE).
4E96LD A,(HL)
4E97OR A
4E98JP NZ,0BC3poss. Jump to "SYNTAX ERROR".
4E9BLD A,D
4E9COR A
4E9DJP Z,14DF
4EA0EX DE,HL
At this point HL holds the address of the last byte of usable RAM, +1.
GotMem:4EA1DEC HLHL = address of last byte of usable RAM.
4EA2PUSH HL
4EA3LD DE,FF9DDE = -99.
4EA6POP HL
4EA7DEC HLHL = address of last word of usable RAM.
4EA8LD (0A9C),HLStore last_word somewhere.
4EABADD HL,DEHL = HL - 99.
4EACJP NC,0B9DSpong! Inconceivable jump surely?...
4EAFDEC HLHL = last_word - 100.
4EB0PUSH HLKeep it on the stack.
4EB1LD A,84No idea what this bit is for...
4EB3LD (06DF),A
4EB6LD A,70
4EB8LD (06E0),A


2.4 "LINEPRINTER? "

Asks user to identify the printer. Only acceptable answers are 'Q', 'C', or 'O'. If user does not give one of these, the question is repeated.

4EBBLD HL,4F07Print "LINEPRINTER"
4EBECALL 21A8
4EC1CALL 0E36
4EC4JP C,4EBB
4EC7RST 10H
4EC8CP 51A='Q'?
4ECAJP Z,PrinterQ(4F13)
4ECDCP 43A='C'?
4ECFJP Z,PrinterC(4EED)
4ED2CP 4FA='O'?
4ED4JP NZ,4EBBJump back cos no valid answer given.
PrinterO:4ED7LD DE,512ADE = address of PrinterDriver_O.
4EDALD C,AEC = size of PrinterDriver_O.
4EDCLD A,01
4EDEOUT (02),A
4EE0LD A,50
4EE2LD (06DF),A
4EE5LD A,38
4EE7LD (06E0),A
4EEAJP CopyDriver(4EF9)
PrinterC:4EEDLD DE,50A2DE = address of PrinterDriver_C.
4EF0LD C,89C = size of PrinterDriver_C.
4EF2LD A,11
4EF4OUT (03),A
4EF6XOR A
4EF7OUT (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:4EF9LD HL,3C2DHL = address of PrinterDriver
4EFCLD A,(DE)
4EFDLD (HL),A
4EFEINC HL
4EFFINC DE
4F00DEC C
4F01JP NZ,4EFC
4F04JP HighestDisk(4F38)
4F07"LINEPRINTER\0"
PrinterQ:4F13XOR A
4F14OUT (30),A
4F16OUT (32),A
4F18OUT (34),A
4F1AOUT (36),A
4F1COUT (35),A
4F1ELD A,FF
4F20OUT (31),A
4F22OUT (33),A
4F24OUT (37),A
4F26LD A,04
4F28OUT (30),A
4F2AOUT (32),A
4F2COUT (34),A
4F2EOUT (36),A
4F30LD A,FC
4F32OUT (37),A
4F34LD A,FA
4F36OUT (37),A


2.5 "HIGHEST DISK NUMBER? "

todo.

HighestDisk:4F38LD HL,4FBBPrint "HIGHEST DISK NUMBER" and get input.
4F3BCALL 4FF5
4F3ELD (0786),A
4F41LD HL,4E2FHL=0x4E2F + 0x27 * (highest_disk_number + 1).
4F44LD DE,0027
4F47INC A
4F48ADD HL,DE
4F49DEC A
4F4AJP NZ,4F48


2.6 "HOW MANY FILES? "

todo.

4F4DPUSH HLPreserve highest_disk.
4F4ELD HL,4FCFPrint "HOW MANY FILES" and get input.
4F51CALL 4FF5
4F54POP HLHL = highest_disk.
4F55LD (0827),HLStore it somewhere.
4F58LD DE,0829
4F5BLD (0849),AStore file_count somewhere
I think we're initialising a file table here: A table of file_count+1 entries, each entry
4F5EINC A
4F5FLD BC,008ABC=0x8A, poss. file descriptor size?
4F62EX DE,HL
4F63LD (HL),E
4F64INC HL
4F65LD (HL),D
4F66INC HL
4F67EX DE,HL
4F68ADD HL,BC
4F69DEC A
4F6AJP NZ,4F62
4F6DLD (0813),HL


2.7 "HOW MANY RANDOM FILES? "

todo.

4F70LD HL,4FDEPrint "HOW MANY RANDOM FILES" and get input.
4F73CALL 4FF5
4F76LD (0812),A
4F79OR A
4F7AINC A
4F7BCALL 30C0
4F7EINC HL
4F7FLD (06E9),HL
4F82EX (SP),HLHL=HIMEM
4F83LD DE,521DIf HIMEM < 0x521D then jump to "OUT OF MEMORY" error.
4F86RST 20H
4F87JP C,0B9D
4F8APOP DEDE = rand_file
4F8BLD SP,HLSP = HIMEM.
4F8CLD (06E5),HL
4F8FLD (0AD3),HL
4F92EX DE,HL
4F93CALL 0B8EThis func. seems to check that there is enough stack space.
4F96LD A,EHL = DE - HL
4F97SUB L
4F98LD L,A
4F99LD A,D
4F9ASBC H
4F9BLD H,A
4F9CLD BC,FFF0HL = HL - 0x10.
4F9FADD HL,BC
4FA0CALL 17BD
4FA3CALL 4661
4FA6LD HL,5047
4FA9CALL 21A8
4FACLD HL,21A8
4FAFLD (0C63),HL
4FB2LD HL,0BA2
4FB5LD (0002),HL
4FB8JP 4D4C
4FBB"HIGHEST DISK NUMBER\0"
4FCF"HOW MANY FILES\0"
4FDE"HOW MANY RANDOM FILES\0"
4FF4POP HL
4FF5PUSH HL
4FF6CALL 21A8
4FF9CALL 0E36
4FFCJP C,4FF4
4FFFRST 10H
5000CALL 1C64
5003DEC HL
5004RST 10H
5005JP NZ,4FF4
5008LD HL,000F
500BRST 20H
500CJP C,4FF4
500FPOP AF
5010LD A,E
5011RET
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 - 5129Source for PrinterDriver_C
512A - 51??Source for PrinterDriver_O