Model I ROM Explained – Part 1

These 3 pages are a breakdown of the Model I ROM, with comments to help you understand what is going on. The two thing to keep in mind while reading this disassembly are:


  • The ROM had to be one big long program starting from 0000H and ending at 2FFFH and everything it does had to be wedged into that single long block of code. This means that jumps to other locations are a necessity because once a particular portion of the ROM executes, if it was allowed to keep going, unintended portions would also execute. With this, there is a LOT of jumping away.
  • There are only so many variables and only so many Z-80 instructions. There is no Z-80 instruction, for example, LD BC,SP. With this, there is a huge amount of variable swapping. I would dare say that whatever part of the ROM isn’t jumping, is just swapping variables around. The ROM would be a fraction of the size if there were more variables and more Z-80 instructions.

0000H-0004H – POWER UP ROUTINE – “DOSCLD” or “$RESET”

0000H
DI
Disables the interrupts and turns off clock
0001H
XOR A
Clears the A register and status
0002H-0004H
Go to the Level II BASIC initialization routine
0005H-0007H
Go to RST 0008H code via 4000H
0008H
“SYNTAX”
(RST 008H)
Jumps to 4000H. 4000H passes control to 1C96H. This routine is used for scanning strings. It compares the character pointed to by the HL register pair with the character pointed to by the return address on the top of the stack (Note that a RST instruction is in effect a CALL and places a return address on the stack) formula: (HL)=((SP))? If they are not equal an SN ERROR will result; if they are equal then the return address on the stack will be incremented to bypass the test character and control will be passed to RST 10H logic. RST 8H is used to look for expected characters in a string and then return with (HL) pointing to the next non-blank character. (see RST l0H) (BC and DE registers unaffected.). This routine can be used by CALLing 1C96H or RST 8H.
This is the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase)

000BH-000CH – DISK ROUTINE – “WHERE”

000BH
POP HL
Get the address from the stack and put it in register pair HL
000CH
JP (HL)
Jump to the location of the address in register pair HL

000DH-000FH – DISK BOOTSTRAP – “BOOT$”

000DH-000FH
“DBOOT”
Jump to the disk load and run sector routine at 069FH

0010H-0012H – RST 10 – GET A CHARACTER FROM THE BUFFER

0010H
(RST 010H)
Jumps to 1D78H (RST 0010H vector) through 4003H.

This routine INCrements HL and tests the characters pointed to by the HL register pair. It will bypass any spaces and CHAR’S 9 and 10 (shifted left and down arrows respectively). Upon return from this routine HL will point to the next non-blank character; the carry flag will be SET (C=1) if HL is pointing to a number and the Z flag will be SET if the character pointed to happens to be zero (ASCII 30H) or 3AH (“:”). The carry flag will be RESET (0) if the character is non-numeric. (BC and DE registers are unaffected) This routine can be used by CALLing 1D78H or RST l0H

0013H-0017H – “GET$” – INPUT ROUTINE

  • This routine Inputs a byte from an input device. When calling, DE = starting address of DCB of device. On exit, A = byte received from device, Z set if device ready. Uses AF.
0013H
“INBYT”
PUSH BC
Save the value in register pair BC on the stack
0014H-0015H
LD B,01H
Load register B with the device type entry code of 01H
0016H-0017H
JR 0046H
JR CIO$
Jump to the Level II BASIC driver entry routine at 0046H
0018H
“RST18”
(RST 018H)
JP 4006H
JP RST3$
Jumps to 1C90H through 4006H. This routine can be called by using RST 18H or CALL lC90H. It compares two 16 bit values in HL and DE and sets the S and Z flags accordingly (they are set in the same way as for a normal 8 bit CP). All registers are unchanged except for A.
This is the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)

001BH-001EH – “PUT$” – DRIVER ENTRY ROUTINE – Part 1

  • This routine outputs a byte to a device. When calling, A = output byte, DE = starting address of DCB of device. On exit, Z set if device ready. Uses AF.
001BH
“OUTBYT”
PUSH BC
Save the value in register pair BC on the stack
001CH-001DH
LD B,02H
Load register B with the device type entry code of 02H
001EH-001FH
JR 0046H
JR CIO$
Jump to the Level II BASIC driver entry routine at 0046H
0020H
(RST 020H)
This routine jumps to 25D9H through 4009H. If the NTF=8 then C=RESET or else C=SET, Z flag will be SET if NTF=3 (S flag is valid also.). After execution of RST 20H or CALL 25D9H, A will contain the value NTF-3, all other registers are unchanged.
Returns a combination of STATUS flags and unique numeric values in the A Register according to the data mode flag (40AFH). Integer = NZ/C/M/E and A is -1; String = Z/C/P/E and A is 0; Single Precision = NZ/C/P/O and A is 1; and Double Precision is NZ/NC/P/E and A is 5. This CALL is usually made to determine the type of the current value in REG 1. It should be used with caution, however since the mode flag and REG 1 can get out of phase particularly if some of the CALLS described here are used to load REG 1

0023H-0027H – “$CTL” – DISK ROUTINE

0023H
“CTLBYT”
PUSH BC
Save the value in register pair BC on the stack
0024H-0025H
LD B,04H
Load register B with the device type entry code of 04H
0026H-0027H
Jump to the Level II BASIC driver entry routine at 0046H
0028H
(RST 028H)
Jumps to 400CH which contains C9H (RET) under Level II BASIC. This vector is only used by Disk BASIC. It is called by the BREAK key routine, and can be used to intercept the BREAK key logic.
This is the DOS FUNCTION CALL routine at RST 28 (which passes request code in A-register to DOS for processing. Returns for non-disk system. For disk systems, the A register must contain a legitimate DOS function code. If the code is positive, the CALL is ignored and control returns to the caller. Note that the DOS routine discards the return address stored on the stack by the RST instruction. After processing control will be returned to the previous address on the stack)

002BH-002FH – KEYBOARD ROUTINE – “$KBD” or “KBDSCN” or “$KBCHAR”

  • Keyboard scanning routine. After CALLing 2BH, the A register will contain the ASCII value for the key that was pressed. The A register will contain 00H if no key was pressed at the time. Apart from the AF register pair the DE register pair is also used by the routine.
    This Routine Performs an instantaneous scan of the keyboard. If no key is depressed control is returned to the caller with the A register and status register set to zero. If any key (except the BREAK key) is active the ASCII value for that character is returned in the A-register. If the BREAK key is active, a RST 28 with a system request code of 01 is executed. The RST instruction results in a JUMP to the DOS Exit 400C. On non-disk systems the Exit returns, on disk systems control is passed to SYS0 where the request code will be inspected and ignored, because system request codes must have bit 8 on. After inspection of the code, control is returned to the caller of 002B. Characters detected at 002B are not displayed. Uses DE, status, and A register
  • Of the 3 keyboard scanning routines, this is the most fundamental one. If no key is pressed when the CALL is executed, the code falls through with A = 00H. If you want to wait for a key to be pressed, you would use CALL 0049 or you would write a routine that jumps back to the call if A is 0.
  • This routine loads DE with address of keyboard DCB and scans keyboard. On exit, if no key pressed the A register will contain a zero byte, else the character input from the keyboard wi 11 be returned in A. Character is not echoed to video. Uses AF,DE (to save DE use routine at 03588).
002BH-002DH
“KBSCAN”
LD DE,4015H
Load register pair DE with the starting address of the keyboard device control block.
Note: 4015H holds Keyboard DCB – Device type
002EH-002FH
Jump to the Level II BASIC driver entry routine
0030H
(RST 030H)
This location passes control to 400FH which contains a RET (C9H) under Level II. This location is only used by a Disk system.
This is the LOAD DEBUG routine, and loads the DEBUG program and transfers control to it. When DEBUG processing is complete, control is returned to the orginal caller. For non-disk systems control is returned immediately

0033H-0037H – VIDEO ROUTINE – “$DSP” or “$VDCHAR”

  • Character print routine. A CALL 33H will print a character at the current cursor position. The A register must contain the ASCII code for the character or graphics figure that is to be printed before CALLing this routine. The DE register pair is used by the routine.
    A call to 0033H displays the character in the A-register on the video. Control codes are permitted. All registers are used.
0033H-0035H
“VDCHAR”
LD DE,401DH
Load register pair DE with the starting address of the video display device control block.
Note: 401DH holds Video DCB – Device type
0036H-0037H
Jump to the Level II BASIC driver entry routine at 001BH
0038H
(RST 038H)
This location will pass control to 4012H. This location is only used by a Disk system.
This is the INTERRUPT ENTRY POINT routine at RST 38H which is the system entry point for all interrupts. It contains a jump to a section of code in the Communications Region designed to field interrupts. That section of code consists of a DI (disables further interrupts) followed by a RET (returns to the point of interrupt) for non-disk systems, or a jump to an interrupt processor in SYSO if it is a DOS system. For DOS systems the interrupt handler consists of a task scheduler, where the exact cause of the interrupt is determined (usually a clock interrupt) and the next task from the task control block is executed. After task completion, control returns to the point of interrupt

003BH-003FH – PRINTER ROUTINE – “$PRT” or “PRCHAR” or “$PRCHAR”

  • Character LPRINT routine. Same as 33H but outputs to line printer. (Contents of A register will be printed).
  • A call to 003BH causes the character contained in the C-register to be sent to the printer. A line count is maintained by the driver in the DCB. When a full page has been printed (66 lines), the line count is reset and the status register returned to the caller is set to zero. Control codes recognized by the printer driver are:
    • 00=Returns the printer status in the upper two bits of the A-register and sets the status as zero if not busy, and non-zero if busy.
    • OB=Unconditionally skips to the top of the next page.
    • OC=Resets the line count (DCB 4) and compares its previous value to the lines per page (DCB 3) value. If the line count was zero, no action is taken. If the line count was non-zero then a skip to the top form is performed.
    • OD=Line terminator. Causes line count to be incremented and tested for full page. Usually causes the printer to begin printing.
003BH-003DH
“LPTBYT”
LD DE,4025H
Load register pair DE with the starting address of the printer device control block.
Note: 4025H holds Printer DCB – Device type
003EH-003FH
JR 001BH
JR $PUT
Jump to the Level II BASIC printer driver entry routine

0040H-0042H – INPUT ROUTINE – “KBLINE” or “KEYIN$”

0040H-0042H
Jump to the “WAIT FOR NEXT LINE” keyboard input routine at 05D9 (which takes keyboard entry until a carriage return, a break, or buffer overrun occurs)
0043H
RET
0044H
NOP
0045H
NOP

0046H-0048H – DRIVER ENTRY ROUTINE – Part 2

0046H-0048H
“DRIVRV”
Jump to the Level II BASIC keyboard driver entry routine
0049H-004BH
“GETCHR”
Go scan the keyboard and return with the key pressed, if any, in register A.
A CALL to this memory location returns as soon as any key on keyboard is pressed. ASCII value for character entered is returned in A register. Uses A, status, and DE registers

0049H-004FH – KEYBOARD ROUTINE – “$KBWAIT”

  • A call to 0049H returns as soon as any key on keyboard is pressed, exactly how the INKEY$ function works in BASIC. ASCII value for character entered is returned in A register. If you don’t want the program to hold while waiting for a key, you would use CALL 002BH instead.
0049H
Character input routine. This routine is the same as 2BH (=Scan the Keyboard routine) except that it will not return until a key is pressed
004CH
OR A
Check the value in register A to see if a key was pressed
004DH
RET NZ
Return if a key was pressed
004EH-004FH
Loop until a key is pressed

0050H-005FH – KEYBOARD LOOKUP TABLE

  • This is a table of control characters used by BASIC.
0050H
“KBTBL”
0DH
ENTER (0DH)
0051H
0DH
Shift ENTER (0DH)
0052H
1FH
CLEAR (1FH)
0053H
1FH
Shift CLEAR (1FH)
0054H
01H
BREAK (01H)
0055H
01H
Shift BREAK (01H)
0056H
5BH
Up Arrow (5BH)
0057H
1BH
Shift Up Arrow (1BH)
0058H
0AH
Down Arrow (0AH)
0059H
1AH
ROM before v1.3 – Shift Down Arrow (1AH); ROM v1.3 – NOP to permit Shift-Down-Arrow to act as a control key
005AH
08H
Left Arrow (08H)
005BH
18H
Shift Left Arrow (18H)
005CH
09H
Right Arrow (09H)
005DH
19H
Shift Right Arrow (19H)
005EH
20H
SPACE (20H)
005FH
20H
Shift SPACE (20H)

0060H-0065H – DELAY ROUTINE – “$DELAY”

  • This is a delay loop. The BC register pair is used as the loop counter. The duration of the delay, in microseconds, is the value of BC times 14.65. Register A is used.
0060H
DEC BC
Decrement the counter in register pair BC
0061H-0062H
LD A,B
OR C
There is no way to COMPARE BC against anything, so the common “trick” is to load Register A with Register B and then OR it against Register C. If you do this, Register A can only be zero if both Registers B and C are zero.
0063H-0064H
Loop until the counter in register pair BC is equal to zero
0065H
RET
Return
0066H-0068H
“NMI”
LD SP,0600H
Set the stack pointer to 0600H.
This is the location to which program control jumps when the RESET button is pressed (Non Maskable Interrupt address)

0069H-0074H – NMI INTERRUPT ROUTINE (RESET) – “$INITIO”

  • This part of the initialization routine checks to see if a disk drive is connected. If so, it will jump to 00H. (This is why the reset button will reinitialize DOS.)
0069H-006BH
LD A,(37ECH)
Load register A with the disk controller status (stored in 37ECH)
006CH
INC A
Increment the disk controller status in register A
006DH-006EH
CP 02H
Check the value in register A to see if a disk is present. It is usually FFH if there is no expansion interface operating
006FH-0071H
If a disk is present, go to the Level II BASIC power up routine
0072H-0074H
Since we are without disk drives at this, this would be for power on or reset … so jump to the Level II BASIC READY routine at 06CCH

0075H-0104H – INITIALIZATION ROUTINE

  • This is part of the Level II initialization procedure. It moves a block of memory from 18F7H to l9lEH up to 4080H to 40A7H. (reserved RAM. area).
    Note: 4080H-408DH is a division support routine.
0075H-0077H
“CSTLII”
LD DE,4080H
Load register pair DE with the ROM storage location of the Level II BASIC division routine.
Note: 4080H-408DH is a division support routine
0078H-007AH
LD HL,18F7H
Load register pair HL with the RAM storage location of the Level II BASIC division routine
007BH-007DH
LD BC,0027H
Load register pair BC with the length of the Level II BASIC division routine (39 bytes)
007EH-007FH
LDIR
Move the Level II BASIC division routine in ROM (18F7H-191DH) to RAM (4080H-40A6H)
0080H-0082H
LD HL,41E5H
Continue with the communication region initialization by loading register pair HL with a RAM pointer to 41E5H
0083H-0084H
LD (HL),3AH
Save a 3AH (which a “:”) at the location of the memory pointer in register pair HL (which is 41E5H)
0085H
INC HL
Increment the memory pointer in register pair HL from 41E5H to 41E6H
0086H
LD (HL),B
Zero out 41E6H (the location of the memory pointer in register pair HL)
0087H
INC HL
Increment the memory pointer in register pair HL from 41E6H to 41E7H
0088H-0089H
LD (HL),2CH
Save a 2CH (which is a “,”) at 41E7H (the location of the memory pointer in register pair HL)
008AH
INC HL
Increment the memory pointer in register pair HL from 41E7H to 41E8H, which is the input/output buffer
008BH-008DH
LD (40A7H),HL
This loads the input buffer pointer (held at 40A7H) with the keyboard buffer location address of 41E8H. (40A7H is the I/O buffer pointer and can be changed to relocate the buffer.). Save the value in register pair HL as the starting address of the keyboard input buffer area.
Note: 40A7H-40A8H holds the input Buffer pointer
008EH-0090H
LD DE,012DH
In prepartaion for a jump, load register pair DE with the starting address of the ?L3 ERROR routine

0091H-0104H – The rest of the initialization routine. First, it fills the RAM locations pointing to all 28 DOS BASIC commands, set them to pointo ?L3 ERROR, ask MEMORY SIZE ?, sets the memory pointers accordingly and prints RADIO SHACK LEVEL II BASIC , then it jumps to 1A19H which is the entry point for the BASIC command mode.

0091H-0092H
LD B,1CH
Since there are 28 pre-defined DOS BASIC commands in ROM, load register B with the number of times (=28) to save the jump to the ?L3 ERROR routine
0093H-0095H
LD HL,4152H
Load register pair HL with the starting address of the Disk Basic links (which is 4152H) in preparation for generating an error if disk basic commands are attempted.
Note: 4152H-41A3H holds Disk Basic links
0096H-0097H
LD (HL),0C3H
Save a C3H (the first OPCODE for JP nnnn) to the first of every 3 byte instruction in the Disk Basic command list
0098H
INC HL
Increment the memory pointer in register pair HL to point to the 2nd of each 3 byte instruction in the Disk Basic command list
0099H
LD (HL),E
Save the LSB of the ?L3 ERROR routine’s starting address in register E (i.e., a 2DH) to the 2nd of each 3 byte instruction in the Disk Basic command list
009AH
INC HL
Increment the memory pointer in register pair HL to the 3rd of each 3 byte instruction in the Disk Basic command list
009BH
LD (HL),D
Save the MSB of the ?L3 ERROR routine’s starting address in register D (i.e., a 01H) to the 3rd of each 3 byte instruction in the Disk Basic command list
009CH
INC HL
Increment the memory pointer in register pair HL to the 1st byte of the next Disk Basic command in the list
009DH-009EH
Do this 28 times (=84 locations) until all of the Disk Basic links have been set to jump to the ?L3 ERROR routine
009FH-00A0H
LD B,15H
Load register B with the number of DOS links to set to RETs. Note: HL is 41A6H at this point.
00A1H-00A2H
LD (HL),0C9H
Save a C9H to the location of the memory pointer in register pair HL fill it with RET instructions (C9H is RET)
00A3H
INC HL
Increment the memory pointer in register pair HL, as it is irrelevant what this memory location holds since RET is a single OPCODE.
00A4H
INC HL
Increment the memory pointer in register pair HL, as it is irrelevant what this memory location holds since RET is a single OPCODE.
00A5H
INC HL
Increment the memory pointer in register pair HL to point to the next error jump instruction
00A6H-00A7H
Loop from 4156H until all of the DOS links have been set to RETs

001BH-001FH – VIDEO AND PRINTER ROUTINE

00A8H-00AAH
LD HL,42E8H
Load register pair HL with the starting address of user RAM (which is 42E8H)
00ABH
LD (HL),B
Zero 42E8H (i.e., the location of the memory pointer in register pair HL)
00ACH-00AEH
LD SP,41F8H
Set the current stack pointer to 41F8H (which is 16888)
00AFH-00B1H
Go initialize the Level II BASIC variables and pointers
00B2H-00B4H
Call the CLEAR SCREEN routine at 01C9 (which clears the screen, changes to 64 characters, and homes the screen)
00B5H-00B7H
LD HL,0105H
Load register pair HL with the starting address of the MEMORY SIZE? message in ROM
00B8H-00BAH
Call the WRITE MESSAGE routine at 28A7H to print the message pointed to by HL.
NOTE:
  • The routine at 28A7 displays the message pointed to by HL on current system output device (usually video).
  • The string to be displayed must be terminated by a byte of machine zeros or a carriage return code 0D.
  • If terminated with a carriage return, control is returned to the caller after taking the DOS exit at 41D0H (JP 5B99H).
00BBH-00BDH
Print a “?” and get input from the keyboard
00BEH-00BFH
If the BREAK key was pressed, ask again. Note: 1BB3H jumps around A LOT but it is 0661H whcih processes a BREAK key, and starts by setting the carry flag
00C0H
Since we now need to increment the input buffer pointer until it points to the first character of the input, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY flag if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
00C1H
OR A
Set the status flag based on if the character at the location of the input buffer pointer in register A is an end of the input character (00H)
00C2H-00C3H
Jump forward to 00D6H if there was a response to the MEMORY SIZE? question
00C4H-00C6H
“MEMSIZ”
LD HL,434CH
If just an ENTER was hit, need to figure it out dynamically, so load register pair HL with the starting address for the memory size check
00C7H
INC HL
We are going to start testing RAM at 17229 (i.e., 434DH) toward 65535, so increment the memory pointer in register pair HL
00C8H-00C9H
LD A,H
OR L
There is no way to COMPARE HL against anything, so the common “trick” is to load Register A with Register H and then OR it against Register L. If you do this, Register A can only be zero if both Registers H and L are zero.
00CAH-00CBH
Since we need to scan all the way up to 65535, jump to 00E7H (which drops the memory size pointer by 1) if the current memory pointer in register pair HL is equal to zero
00CCH
LD A,(HL)
Load register A with the value at the location of the current memory pointer in register pair HL
00CDH
LD B,A
Load register B with the value in register A to preserve it, as A is about to get used
00CEH
CPL
Complement the value in register A (which is basically a test pattern)
00CFH
LD (HL),A
Save the test pattern in register A to the location of the current memory pointer in register pair HL
00D0H
CP (HL)
Check to see if the value at the location of the memory pointer in register pair HL is the same as the value in register A
00D1H
LD (HL),B
Put back the original memory value (which was saved in B) to the location of the memory pointed in register pair HL
00D2H-00D3H
If the address exists, loop back to 00C7H until the end of memory is found
00D4H-00D5H
If the address didn’t exist, jump to 00E7H (which goes to he next address and tries again)
00D6H-00D8H
Here the MEMORY SIZE? answer is in HL so call the ASCII TO INTEGER routine at 1E5AH (which will put the answer into DE in integer format).
NOTE:
  • The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped
00D9H
OR A
Check to see if register A is equal to zero
00DAH-00DCH
Display a ?SN ERROR if register A is not equal to zero
00DDH
EX DE,HL
Swap DE (where the integer version of the MEMORY SIZE? answer is located) and HL, so that register pair HL now has with the MEMORY SIZE answer again, but in integer format
00DEH
DEC HL
Decrement the MEMORY SIZE? in register pair HL
00DFH-00E0H
LD A,8FH
Load register A with a memory test value of 8F or 10001111
00E1H
LD B,(HL)
Load register B with the value at the location of the MEMORY SIZE? pointer in register pair HL (to save the data thats there)
00E2H
LD (HL),A
Put the test pattern (in A which is 8FH) into that the location of the MEMORY SIZE? pointer in register pair HL
00E3H
CP (HL)
Check to see if the value in the memory location set in HL matches the test pattern in A
00E4H
LD (HL),B
Restore the old memory contents back
00E5H-00E6H
The test at MEMORY SIZE? -1 failed so we have to ask MEMORY SIZE again by jumping to 00B5H
00E7H
DEC HL
Decrement the memory size pointer in register pair HL, so it is the amount of memory – 2
00E8H-00EAH
LD DE,4414H
Load register pair DE with the minimum MEMORY SIZE? response (which is 17428)
00EBH
Now we need to check to see if the MEMORY SIZE? pointer (in HL) is less than the minimum MEMORY SIZE? response (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status register as: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
00ECH-00EEH
If C is set, then the amount of actual memory (in HL) is less than the minimum memory required (in DE), so we have to go to the Level II BASIC error routine and display an OM ERROR
00EFH-00F1H
LD DE,FFCEH
Load register pair DE with the default size of the string area (i.e., negative fifty)
00F2H-00F4H
LD (40B1H),HL
Save the MEMORY SIZE? amount (which is in HL) to 40B1H (which holds the MEMORY SIZE? pointer)
00F5H
ADD HL,DE
Subtract the size of the string data (which was -50) from the highest memory address (stored in HE)
00F6H-00F8H
LD (40A0H),HL
Save the start of string space pointer (which is now held register pair HL) to 40A0H.
Note: 40A0H-40A1H holds the start of string space pointer
00F9H-00FBH
Go initialize/reset the Level II BASIC variables and pointers
00FCH-00FEH
LD HL,0111H
Load register pair HL with the starting address of the RADIO SHACK LEVEL II BASIC message. 00FFH-0101H Go display the RADIO SHACK LEVEL II BASIC message
00FFH-0101H
We need to display the RADIO SHACK LEVEL II BASIC message so we call the WRITE MESSAGE routine at 28A7.
NOTE:
  • The routine at 28A7 displays the message pointed to by HL on current system output device (usually video).
  • The string to be displayed must be terminated by a byte of machine zeros or a carriage return code 0D.
  • If terminated with a carriage return, control is returned to the caller after taking the DOS exit at 41D0H (JP 5B99H).
0102H-0104H
Go to the Level II BASIC READY routine

0105H-0110H – MESSAGE STORAGE

0105H-0110H
“DMEMSZ”
MEMORY SIZE? message is stored here
*0108H-010DH
“SIZE”+00H
In ROM 1.2, this shortend the “MEMORY SIZE”
*010EH-011BH
“R/S L2
BASIC”
In ROM 1.2, this is shortend version
*011CH
PUSH BC
*In R/S L2 BASIC, this is the debounce routine. First, Put the Row Address in BC into the stack so BC can be used for the debounce routine
*011DH-011FH
LD BC,0500H
Put 0500H into BC (which would be the debounce delay)
*0120H-0122H
CALL 0060H
Call the delay at 0060H based on the delay count in BC (which is 7.33 milliseconds)
*0123H
POP BC
Restore the Row Address back to BC
*0124H
LD A,(BC)
Reload the original flags from active row
*0125H
AND E
Combine the current flag lists with the original flag bits
*0126H
RET Z
Return to caller if zero because the row was not active on the second test
*0127H
LD A,D
Otherwise, we have a legitimate active row
*0128H
RCLA
Multiply the row index by 2. (Note: This was needed because a RCLA was sacrificed at the call location to give up the bytes needed for the call)
*0129H
RCLA
Multiply the row index by 2 again. (Note: This was needed because a RCLA was sacrificed at the call location to give up the bytes needed for the call)
*012AH-012CH
JP 03FEH
Resume the keyboard driver routine

012DH-0131H – ?L3 ERROR ROUTINE

012DH-012EH
“L3ERR”
LD E,2CH
Load register E with the ?L3 ERROR code of 2CH
012FH-0131H
Go to the Level II BASIC error routine with 2CH loaded into Register E

0132H-0134H – LEVEL II BASIC “POINT” COMMAND ENTRY POINT
POINT

0132H
“GRPHCS”
Since we need to bump the current BASIC program pointer until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-register and clears the CARRY flag if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
0133H
XOR A
A will wind up being 0 if the POINT command was entered … otherwise
0134H
013E80
Z-80 Trick! The byte at this memory location, 01H, is there to turn the real instruction that follows (the operative action of the SET command) into a harmless LD BC,xxxx. This way, they didn’t have to jump over SET or RESET to get to the common graphics code. If parsing straight down, this loads BC with 0380H and then moves to 0136H. But if jump straight to 0136H, you skip that 01H opcode, and get a real instruciton of 3EH 80H

0135H-0137H – LEVEL II BASIC SET COMMAND ENTRY POINT
SET

0135H-0136H
“SET”
LD A,80H
Load register A with 80H (which is 128) which is SET
0136H
1A
Z-80 Trick – See the note at 0134H for an explanation

0138H-0139H – LEVEL II BASIC RESET COMMAND ENTRY POINT
“RESET”

0138H-0139H
“RESET”
LD A,01H
Load register A with 01H which is RESET

013AH-019CH GRAPHICS ROUTINE
“GRAPH”

  • Common code for SET/RESET/POINT – A will be 0 if POINT, 80H if SET and 1 for RESET.
013AH
PUSH AF
Save the graphics mode in register A on the stack so we can use A for other things
013BH-013CH
Since SET/RESET/POINT all need a “(” to start with, call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase)
013DH-013FH
CALL 2B1CH
Go evaluate the expression at the location of the current BASIC program pointer in register pair HL (which is the X variable) and return with the 8-bit value in register A
0140H-0141H
CP 80H
Check to see if the X value in register A is greater than 128
0142H-0144H
If A is greater than 128, go to 1E4AH to display a ?FC ERROR
0145H
PUSH AF
Save the X value in register A on the stack
0146H-0147H
At this point we have SET/RESET/POINT, an open parenthesis, and an X variable, so now we must find a ,. To do this call the COMPARE SYMBOL routine which comparess the symbol in the input string pointed to by HL register to the value in the location following the RST 08 call. If there is a match, control is returned to address of the RST 08 instruction 2 with the next symbol in the Aregister and HL incremented by one. If the two characters do not match, a syntax error message is given and control returns to the Input Phase)
0148H-014AH
Go evaluate the expression at the location of the current BASIC program pointer in register pair HL (which is the Y variable) and return with the 8-bit value in register A
014BH-014CH
CP 30H
Check to see if the Y value in register A is greater than 48
014DH-014FH
If the Y value is greater than 48, go to 1E4AH to display a ?FC ERROR
0150H-0151H
“SETRES”
LD D,0FFH
Prepare to divide y coordinate by 3 … load register D with starting quotient
0152H
INC D
Increment the quotient in register D
0153H-0154H
SUB 03H
Divide by subtraction; in this case subtract 3 from register A
0155H-0156H
Loop until register D equals the Y value divided by 3
0157H-0158H
ADD 03H
Make the remainder positive by adjust the remainder in register A by adding back 3
0159H
LD C,A
Save the remainder in register C
015AH
POP AF
Get the X value from the stack and put it in register A
015BH
ADD A,A
Multiply the X value in Register A by two, storing the result in Register A
015CH
LD E,A
Load Register E with the newly doubled Register A
015DH-015EH
LD B,02H
Load register B with the number of times to shift register pair DE (which is 2)
015FH
LD A,D
Load Register A with the adjusted Y value in register D
0160H
RRA
Divide the adjusted Y value in Register A by two
0161H
LD D,A
Save the new Y value in Register A in register D
0162H
LD A,E
Load Register A with the adjusted X value in register E
0163H
RRA
Divide the adjusted X value in Register A by two
0164H
LD E,A
Load register E with the new X value in Register A
0165H-0166H
Loop until the memory offset in register pair DE has been figured
0167H
LD A,C
Now we need to computer the position of the point so load Register A with the value in register C
0168H
ADC A,A
Multiply the value in Register A by two and add the value of the Carry flag to Register A
0169H
INC A
Increment the value in Register A
016AH
LD B,A
Save the bit position in Register A in register B
016BH
XOR A
Zero Register A and reset the Carry flag
016CH
SCF
Set the Carry flag
016DH
ADC A,A
Add the value of the Carry flag to Register A
016EH-016FH
Loop back to the prior instruction until the graphic mask has been completed in Register A
0170H
LD C,A
Save the graphic mask in Register A in register C
0171H
LD A,D
Load Register A with the MSB of the video memory offset in register D
0172H-0173H
OR 3CH
Mask the MSB of the video memory offset in Register A with 0011 1100 so that it will point to the correct location in video memory
0174H
LD D,A
Save the MSB of the video memory pointer in Register A in register D
0175H
LD A,(DE)
Load Register A with the character at the location of the video memory pointer in register pair DE
0176H
OR A
Check to see if the character in Register A is a graphic character
0177H-0179H
Skip the next optcode if the character in Register A is a graphic character
017AH-017BH
LD A,80H
Load Register A with a blank graphic character which is CHR$(128)
017CH
LD B,A
Set the flags according to the graphic mode in Register A.

Save the graphic character in Register A in register B
017DH
POP AF
Get the graphic character from the stack (Register B) and put it in Register A
017EH
OR A
Set the flags according to the graphic mode in Register A
017FH
LD A,B
Get the graphic character from register B and put it in Register A
0180H-0181H
Jump forward to 0192H if the graphic mode is POINT
0182H
LD (DE),A
Save the graphic character in Register A at the location of the video memory pointer in register pair DE
0183H-0185H
Jump forward to 018FH if the graphic mode is SET
0186H
LD A,C
Load Register A with the graphic mask in register C
0187H
CPL
Reverse the graphic mask in Register A
0188H
LD C,A
Load register C with the adjusted graphic mask in Register A
0189H
LD A,(DE)
Load Register A with the character at the location of the video memory pointer in register pair DE
018AH
AND C
RESET the graphic bit by combining the graphic mask in register C with the graphic character in Register A
018BH
LD (DE),A
Save the adjusted graphic character in Register A at the location of the video memory pointer in register pair DE
018CH-018DH
CF 29H
Check the syntax. The character at the location of the current BASIC program pointer in register pair HL must be a ) character (“)” is 29H)
018EH
RET
Return
018FH
OR C
SET the graphic bit by combining the graphic mask in register C with the graphic character in Register A
0190H-0191H
Jump back a few bytes to 018BH
0192H
AND C
POINT the graphic bit by combining the graphic mask in register C with the graphic character in Register A
0193H-0194H
ADD 0FFH
Subtract one from the value in Register A
0195H
SBC A,A
Adjust the value in Register A so that A will equal zero if the bit was off in Register A
0196H
PUSH HL
Save the current BASIC program pointer in register pair HL on the stack
0197H-0199H
Save the value in Register A as the current result in REG 1
019AH
POP HL
Get the current BASIC program pointer from the stack and put it in register pair HL
019BH-019CH
Jump to 018CH

019DH-01C8H – LEVEL II BASIC INKEY$ ROUTINE

019DH
“INKEY”
Since we need to bump the current BASIC program pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-Register And clears the CARRY flag if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
019EH
PUSH HL
Save the current BASIC program pointer in register pair HL on the stack
019FH-01A1H
LD A,(4099H)
Put the last key pressed (stored at 4099H) and put it in Register A
01A2H
OR A
Set the status flags
01A3H-01A4H
Jump to 01ABH (to skip the next character scan) if a key has been pressed
01A5H-01A7H
Go scan the keyboard
01A8H
OR A
Set the status flags
01A9H-01AAH
Jump to 01BCH if a key wasn’t pressed
01ABH
PUSH AF
Save the key pressed in Register A on the stack
01ACH
XOR A
Zero Register A and clear the A Register status flags
01ADH-01AFH
LD (4099H),A
Save the value in Register A as the last key pressed (which is kept at 16537).
Note: 4099H holds the last key pressed
01B0H
INC A
Increment the value in Register A (which is going to represet the size of the character string to be built)
01B1H-01B3H
Make sure there is room for this character string by calling 2857H to make an entry in string space
01B4H
POP AF
Get the last key pressed from the stack and put it in Register A
01B5H-01B7H
LD HL,(40D4H)
Load register pair HL with the string’s starting address (which is kept in 40D4H)
01B8H
LD (HL),A
Save the last key pressed in Register A at the location of the string pointer in register pair HL
01B9H-01BBH
Go save the string’s VARPTR as the current result
01BCH-01BEH
LD HL,1928H
Load register pair HL with the starting address of the “READY” message (which is 6440)
01BFH-01C1H
LD (4121H),HL
Save the address in register pair HL as the current result in REG 1 (which is 16673)
01C2H-01C3H
LD A,03H
Load Register A with a string number type flag
01C4H-01C6H
LD (40AFH),A
Save the value in Register A as the current number type (which is at 16559).
Note: 40AFH holds Current number type flag
01C7H
POP HL
Get the current BASIC program pointer from the stack and put it in register pair HL
01C8H
RET
Return

01C9H-01D2H – LEVEL II BASIC CLS ROUTINE – “$VDCLS”

  • A CALL lC9H will clear the screen, select 64 characters and home the cursor. All registers are used.
  • To use a ROM call to clear the screen, CALL 01C9H. The cursor is reset to the home position, which is 3C00H.
01C9H-01CAH
LD A,1CH
Load Register A with the ASCII character to home the cursor
01CBH-01CDH
Go send the character in Register A (i.e., the ASCII character to home the cursor) to the video display
01CEH-01CFH
LD A,1FH
Load Register A with the ASCII character to clear to the end of the screen
01D0H-01D2H
Go send the character in Register A (i.e., the ASCII character to clear to the end of the screen) to the video display

01D3H-01D8H – LEVEL II BASIC RANDOM ROUTINE
RANDOM

  • This is part of the RANDOM routine which takes a value out of the REFRESH register, stores it in location 40ABH and then returns.
    A call to 01D3H reseeds the random number seed (location 40AB) with the current contents of the refresh register.
  • NOTE: To run a RANDOM (seed the random number generator) via a ROM call just call CALL 01D3H. This causes the contents of R (memory refresh) to be stored in 40ABH. The entire 24 bit seed is stored in 40AAH-40ACH.
01D3H
“RANDOM”
LD A,R
Load Register A with the current value of the refresh register
01D5H-01D7H
LD (40ABH),A
Save the pseudi-random value in Register A to 40ABH (the random number seed)
01D8H
RET
Return

01D9H-01F7H – CASSETTE ROUTINE

01D9H-01DBH
“CWBIT”
“CTPULS”
LD HL,0FC01H
Load register pair HL with the command to send to the cassette … here, a top of pulse
01DCH-01DEH
CALL 0221H
CALL CTCHG
Go send the command to the cassette controller
01DFH-01E0H
LD B,0BH
Load register B with the delay count of 80 milliseconds
01E1H-01E2H
CT1
DJNZ 01E1H
DJNZ CT1
Loop for delay
01E3H-01E5H
LD HL,0FC02H
Load register pair HL with the command to send to the cassette … here, a bottom of pulse
01E6H-01E8H
CALL 0221H
CALL CTCHG
Go send the command to the cassette controller
01E9H-01EAH
LD B,0BH
Load register B with the delay count of 80 milliseconds
01EBH-01ECH
CT2
DJNZ 01EBH
DJNZ CT2
Loop for delay
01EDH-01EFH
LD HL,0FC00H
Load register pair HL with the command to send to the cassette
01F0H-01F2H
CALL 0221H
CALL CTCHG
Go send the command to the cassette controller … here, a terminate pulse
01F3H-01F4H
LD B,5CH
Load register B with the delay count of 671 milliseconds
01F5H-01F6H
CT3
DJNZ 01F5H
DJNZ CT3
Loop for delay
01F7H
RET
Return

01F8H-01FDH – CASSETTE ROUTINE (TURN OFF CASSETTE) – “$CSOFF”/”$CTOFF”

  • Turns cassette recorder off.
  • To use a ROM call to turn the cassette off, CALL 01F8H
01F8H
CTOFF
PUSH HL
Save the value in register pair HL on the stack
01F9H-01FBH
LD HL,FB00H
Load register pair HL with the command to send to the cassette to turn it off
01FCH-01FDH
JR 0219H
JR CTCHG2
Jump to the cassette driver routine at 0219H
  • 00FEH-0211H – CASSETTE ROUTINE (EVALUATE DRIVE NUMBER)
01FEH
“CTON”
LD A,(HL)
Get the character at the location of the current BASIC program pointer and put it in Register A
01FFH-0200H
SUB 23H
Check to see if the character in Register A is a # character
0201H-0202H
LD A,00H
Zero Register A
0203H-0204H
JR NZ,0212H
JR NZ,DEFDRV
Jump to the TURN ON MOTOR routine at 0212H if the character at the location of the current BASIC program pointer in register pair HL isn’t a # character
0205H-0207H
Go evaluate the drive number at the location of the current BASIC program pointer in register pair HL and return with the drive number in register E
0208H-0209H
We need to see if the character at the location of the current BASIC program pointer in register pair HL is a ,, so call the RST 08H routine to do so
020AH
LD A,E
Need to convert from the negative number to positive so, load Register A with the drive number in register E ..
020BH
AND D
… and combine the MSB of the drive number in register D with the LSB of the drive number in Register A and then ..
020CH-020DH
ADD 02H
… add 2 to make the drive number in Register A positive
020EH-0210H
If the drive number in Register A is invalid, jump to 14E4H to display a FC ERROR
0211H
DEC A
Decrement the drive number in Register A

0212H-021DH – CASSETTE ROUTINE (TURN ON CASSETTE)
“DEFCAS” / “DEFDRV”

  • CALL 212H will select the cassette unit specified in A-Register And starts motor. Units are numbered from one. All registers are used.
  • To use a ROM call to turn on the cassette, execute the following instructions: LD A,0
    CALL 0212H
0212H-0214H
“DEFDRV”
LD (37E4H),A
LD (CASW$),A
Set the current drive as specified by Register A
0215H
PUSH HL
Save the current BASIC program pointer in register pair HL on the stack so we can use HL for the next instruction
0216H-0218H
LD HL,0FF04H
Load register pair HL with the command to turn on the cassette motor
0219H-021BH
“CTCHG2”
CALL 0221H
CALL CTCHG
Go send the “turn on the cassette motor” command stored in HL to the cassette controller
021CH
POP HL
Get the current BASIC program pointer from the stack and put it in register pair HL
021DH
RET
Return
  • 021EH-022BH – CASSETTE ROUTINE
021EH-0220H
“CLRCFF”
“CTSTAT”
LD HL,0FF00H
Load register pair HL with the mask to preserve video controller flags, but otherwise clear the cassette latch
0221H-0223H
“STATFF”
“CTCHG”
LD A,(403DH)
LD A,(CAST$)
Load Register A with the contents of 403DH, which contains, among other things, the screen resolution (32 or 64 wide; Bit 3) the tape relay on/off instruction (Bit 2) and the positive/negative audio pulses (Bits 0-1).
Note: 403DH-4040H is used by DOS
0224H
AND H
Combine the value in register H with the contents of (403DH)
0225H
OR L
Combine the value to send to the cassette in register L with the adjusted value in Register A
0226H-0227H
OUT (0FFH),A
OUT (CASIO$),A
Send the value in Register A to port 255 (which is the cassette and video port)
0228H-022AH
LD (403DH),A
LD (CAST$),A
Save the value in Register A into (403DH).
Note: 403DH-4040H is used by DOS
022BH
RET
Return

022CH-0234H – CASSETTE ROUTINE (BLINK **) – “BCASIN”

  • Alternately displays and clears an asterisk in the upper right hand comer. Uses all registers.
022CH-022EH
“CSTAR”
“BCASIN”
LD A,(3C3FH)
LD A,(DSPAD$+63)
Get the character being displayed in the upper right hand corner of the video display from 3C3FH and put that character in Register A
022FH-0230H
XOR 0AH
If the character in Register A is a * then make it a <SPACE>, else if the character in Register A is a <SPACE> make it a *
0231H-0233H
LD (3C3FH),A
LD (DSPAD$+63),A
Display the character in Register A in the upper right hand comer of the video display
0234H
RET
Return

0235H-0240H – CASSETTE ROUTINE (READ A BYTE) – “$CSIN”/”CASIN”

  • This routine will read a byte from tape. A CALL 235H will return with the byte read from tape in the A Register BC, DE and HL are unchanged.
  • To use a ROM call to read a character from cassette (after the cassette has been turned on and leader and sync have been found), CALL 0235H. The input character will be in the A register. Again, the routine at 0235H must be called frequently enough to sustain the 500 baud rate if more than one character is to be read.
0235H
CASIN
PUSH BC
Save the value in register pair BC on the stack
0236H
PUSH HL
Save the value in register pair HL on the stack
0237H-0238H
LD B,08H
Load Register B (which is what DJNZ decrements to loop) with the number of bits to read (which is 8)
0239H-023BH
CTB0
CALL 0241H
CALL CTBIT
Go read a bit from the cassette recorder (the resulting byte from the 8 bits will be accumulated into the A register)
023CH-023DH
DJNZ 0239H
DJNZ CTB0
Loop that instruction until all eight bits have been read into A
023EH
POP HL
Get the value from the stack and put it in register pair HL
023FH
POP BC
Get the value from the stack and put it in register pair BC
0240H
RET
Return

0241H-0260H – CASSETTE ROUTINE (READ A BIT) – “CTBIT”/”CRBIT”

  • Routine waits for timing pulse, and then performs a timing loop. When the time is up it tests the tape for a bit, which will be “1” if present and “0” if not. A CALL 241H is used by 235H eight times to input one byte.
0241H
“CRBIT”
“CTBIT”
PUSH BC
Save the value in register pair BC on the stack
0242H
PUSH AF
Save the value in Register A on the stack
0243H-0244H
CB0
IN A,(0FFH)
IN A,(CASIO$)
Read a bit from the cassette port (waiting for a clock pulse)
0245H
RLA
Rotate Register A left one bit position with the contents of bit 7 copied to the carry flag. By doing this, the start bit would rotate to the carry flag for easy testing.
0246H-0247H
JR NC,0243H
JR NC,CB0
If NC is set, we do not yet have the start bit, so loop back to 0243H until the start bit is found
0248H-0249H
LD B,40H
No that we have the start bit we need a delay, so load Register B with the delay count of 40H
*0248H-0249H
LD B,60H
In ROM v1.2, load B with a delay count of 60H (=476/703 microseconds) instead of 40H
024AH-024BH
CB1
DJNZ 024AH
DJNZ CB1
Loop (don’t jump unless B is zero; with a decrement of B each time) for delay
024CH-024EH
Go clear the cassette controller so we can get to reading
024FH-0250H
LD B,76H
We need a delay so load Register B with the delay count of 76H
*024FH-0250H
LD B,85H
In ROM v1.2, load B with a delay count of 85H (865/975 microseconds) instead of 76H
0251H-0252H
CB2
DJNZ 0251H
DJNZ CB2
Loop for delay
0253H-0254H
IN A,(0FFH)
IN A,(CASIO$)
Read a bit from the cassette port
0255H
LD B,A
Since we are going to need to use A, load A’s value (the bit read from the cassette port) into Register B
0256H
POP AF
Get the value from the stack (which was the bits already read for this byte) and put it in Register A
0257H-0258H
RLC B
Shift the that data bit read in Register B into the Carry flag
0259H
RLA
Shift the value in the Carry flag (which was B) into Register A
025AH
PUSH AF
Save the value in Register A on the stack because its gonna get erased by the next step
025BH-025DH
CALL 021EH
CALL CTSTAT
Go clear the cassette controller so we can get to reading
025EH
POP AF
Get the value from the stack and put it in Register A
025FH
POP BC
Get the value from the stack and put it in register pair BC
0260H
RET
Return

0261H-0263H – CASSETTE ROUTINE

0261H-0263H
“CW2BYT”
“TWOCSO”
CALL 0264HCALL CASOUT
Write the clock pulse by calling the WRITE ONE BYTE TO CASSETTE routine at 0264H (which writes the byte in the A register to the cassette drive selected in the A register)

0264H-027DH – CASSETTE ROUTINE (WRITE A BYTE) – “$CSOUT”/”CASOUT”

  • Writes the byte in the A register to tape. BC, DE and HL are unchanged by a CALL 264H.
  • To use a ROM call to write a character onto cassette tape (after the cassette has been turned on and leader and sync have been recorded), load the character into the A Register And CALL 0264H. If more than one character is to be written, the CALL 0264H must be executed with sufficient frequency to sustain the 500 baud recording rate. The routine provides automatic timing.
0264H
CASOUT
PUSH HL
Save the value in register pair HL on the stack
0265H
PUSH BC
Save the value in register pair BC on the stack
0266H
PUSH DE
Save the value in register pair DE on the stack
0267H
PUSH AF
Save the value in Register A on the stack
0268H-0269H
LD C,08H
Load register C with the number of bits to be written (i.e., 8)
026AH
LD D,A
Load register D with the byte to be written from Register A because A is about to get used in the next line
026BH-026DH
BYT0
CALL 01D9H
CALL CTPULS
Go write the start/clock bit
026EH
LD A,D
Load Register A with the byte to be written in register D
026FH
RLCA
Shift the bit to be written into the Carry flag
0270H
LD D,A
Save the adjusted byte to be written in Register A in register D
0271H-0272H
JR NC,027EH
JR NC,BYT23
Jump if the bit to be written is equal to zero
0273H-0275H
CALL 01D9H
CALL CTPULS
Go write that (non-zero) bit
0276H
BYT1
DEC C
Decrement the counter in register C
0277H-0278H
JR NZ,026BH
JR NZ,BYT0
Loop until all eight bits have been written
0279H
POP AF
Get the value from the stack and put it in Register A
027AH
POP DE
Get the value from the stack and put it in register pair DE
027BH
POP BC
Get the value from the stack and put it in register pair BC
027CH
POP HL
Get the value from the stack and put it in register pair HL
027DH
RET
Return

027EH-0283H – CASSETTE ROUTINE

027EH-027FH
BYT2
LD B,87H
Load Register B with the delay count of 135
0280H-0281H
BYT3
DJNZ 0280H
DJNZ BYT3
Loop for the delay
0282H-0283H
JR 0276H
JR BYT1
Jump to 0276H to count the number of bits written

0284H-0292H – CASSETTE ROUTINE (TURN ON CASSETTE AND WRITE LEADER)

  • A call to 0284H writes a Level II leader on currently selected unit. The leader consists of 256 (decimal) binary zeros followed by a A5H. Uses the B and A registers.
0284H-0286H
“CWONWL”
Go evaluate the cassette drive number and turn on that cassette drive’s motor
0287H-0288H
“$CSHWR”
LD B,0FFH
Writes tape leader and the A5H sync byte. DE and HL are unchanged.

Load Register B with the number of bytes to be written
  • To use a ROM call to write the cassette leader and sync byte, CALL 0287H
0289H
XOR A
Zero Register A
028AH-028CH
Calls the WRITE ONE BYTE TO CASSETTE routine at 0264H (which writes the byte in the A register to the cassette drive selected in the A register)
028DH-028EH
Loop until leader has been written
028FH-0290H
LD A,A5H
Load Register A with the sync byte value
0291H-0292H
Calls the WRITE ONE BYTE TO CASSETTE routine at 0264H (which writes the byte in the A register to the cassette drive selected in the A register). In this case, it writes the SYNC byte

0293H-029EH – CASSETTE ROUTINE (TURN ON CASSETTE AND READ LEADER)

0293H-0295H
“CRONRL”
Go evaluate the drive number and turn on that cassette drive’s motor
0296H
“$CSHIN”
PUSH HL
Reads from tape until the leader is found, then keeps going until it is bypassed and the sync byte (A5H) is found, when it returns. DE, BC and HL are unchanged by this.

Save the current BASIC program pointer in register pair HL on the stack
  • To use a ROM call to search for leader and sync byte, CALL 0296H
0297H
XOR A
Zero Register A and status flags
0298H-029AH
Go read a byte from the cassette and return with it in Register A
029BH-029CH
CP A5H
Check to see if the byte read from the cassette in Register A is a sync byte
029DH-029EH
Loop until sync byte found

029FH-02A8H – CASSETTE ROUTINE (DISPLAY “**” ON VIDEO)

029FH-02A0H
“CTSTARS”
LD A,”*”
Places the double asterisk in the right top corner to show that the sync byte has been found.

Load Register A with a * character. (“*” is 2AH)
02A1H-02A3H
LD (3C3EH),A
Display the * character in Register A on the video display at location 15422
02A4H-02A6H
LD (3C3FH),A
Display the * character in Register A on the video display at location 15423
02A7H
POP HL
Get the current BASIC program pointer from the stack and put it in register pair HL
02A8H
RET
Return

02A9H-0329H – LEVEL II SYSTEM ROUTINE-ENTRY POINT-02B2H

02A9H-02ABH
“GSYSTR”
Go read 2 bytes from the cassette, which should be the execution address, and return with it in register pair HL
02ACH-02AEH
LD (40DFH),HL
Save the just read execution address from HL into 40DFH.
Note: 40DFH-40E0H holds Used by DOS
02AFH-02B1H
Go turn off the cassette motor
02B2H-02B4H
“SYSTEM”
Go call the DOS link at 41E2H.
In NEWDOS 2.1, this is called during a SYSTEM operation
02B5H-02B7H
LD SP,4288H
Set the stack pointer to 4288H (which is the assumed load address). This location passes control to the routine used by the BASIC command SYSTEM
02B8H-02BAH
GOSUB to display a carriage return on the video display if necessary
02BBH-02BCH
LD A,2AH
Load Register A with an * character (which will form the next prompt)
02BDH-02BFH
Go display the * character in Register A on the video display
02C0H-02C2H
We need a filename now, so go get the input from the keyboard
02C3H-02C5H
If a BREAK key was hit (because the Carry flag is now on), go to the Level II BASIC READY routine
02C6H
Since we need to bump the input buffer pointer in register pair HL until it points to the first character input, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-Register And clears the CARRY flag if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
02C7H-02C9H
Display a ?SN ERROR if there wasn’t any input
02CAH-02CBH
CP 2FH
Check to see if the character at the location of the input buffer pointer in Register A is a / character. “/” is 2FH
02CCH-02CDH
Jump to 031DH if the character at the location of the input buffer pointer in Register A is a /
02CEH-02D0H
Go turn on the cassette motor
02D1H-02D3H
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (whichh reads one byte from the cassette drive specified in Register A, and returns the byte in Register A)
02D4H-02D5H
CP 55H
Check to see if the byte read from the cassette in Register A is a header byte (=55H)
02D6H-02D7H
Loop until the header byte is found
02D8H-02D9H
LD B,06H
If were here, we got the header byte, so load Register B with the length of the filename to read from the cassette (which is 6 characters)
02DAH
“CHKBYT”
LD A,(HL)
Load Register A with the character at the location of the current input buffer pointer in register pair HL
02DBH
OR A
Check to see if the character at the location of the current input buffer pointer in Register A is an end of input character
02DCH-02DDH
Jump out of this ‘read the filename from the cassette’ routine if the character at the location of the current input buffer pointer in Register A is an end of input character
02DEH-02E0H
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (which reads one byte from the cassette drive specified in Register A, and returns the byte in Register A)
02E1H
CP (HL)
Check to see if the character at the location of the current input buffer pointer in register pair HL is the same as the character read from the cassette in Register A
02E2H
INC HL
Increment the input buffer pointer in register pair HL
02E3H-02E4H
Jump to 02D1H (skip to the next program on cassette) if the character at the location of the current input buffer pointer in register pair HL isn’t the same as the character read from the cassette in Register A
*02E2H-02E3H
Jump to 02D1H (skip to the next program on cassette) if the character at the location of the current input buffer pointer in register pair HL isn’t the same as the character read from the cassette in Register A
*02E4H
INC HL
Increment the input buffer pointer in register pair HL
02E5H-02E6H
Loop until the whole of the filename has been read from the cassette and checked against the user response
02E7H-02E9H
Call the BLINK ASTERISK routine at 022CH which alternatively displays and clears an asterisk in the upper right hand corner of the video display
02EAH-02ECH
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (whichh reads one byte from the cassette drive specified in Register A, and returns the byte in Register A)
02EDH-02EEH
CP 78H
Check to see if the byte read from the cassette in Register A is an execution address header byte (which is 120)
02EFH-02F0H
Jump if the byte read from the cassette in Register A is an execution address header byte
02F1H-02F2H
CP 3CH
Check to see if the byte read from the cassette in Register A is a file block header byte (which is 60)
02F3H-02F4H
Loop until either an execution address header byte or a file block header byte is read from the cassette
02F5H-02F7H
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (which reads one byte from the cassette drive specified in Register A, and returns the byte in Register A)
02F8H
LD B,A
Load Register B with the number of bytes to be loaded in Register A
02F9H-02FBH
Go read the file block’s starting address from the cassette and return with it in register pair HL
02FCH
ADD A,L
Add the LSB of the file block’s starting address in register L to the MSB of the file block’s starting address in Register A
02FDH
LD C,A
Load register C with the file block’s starting checksum in Register A
02FEH-0300H
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (which reads one byte from the cassette drive specified in Register A, and returns the byte in Register A)
0301H
LD (HL),A
Save the byte read from the cassette in Register A at the location of the memory pointer in register pair HL
0302H
INC HL
Increment the memory pointer in register pair HL
0303H
ADD A,C
Add the value of the current checksum in register C to the value in Register A
0304H
LD C,A
Load register C with the updated checksum in Register A
0305H-0306H
Loop until the whole file block has been read
0307H-0309H
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (which reads one byte from the cassette drive specified in Register A, and returns the byte in Register A)
030AH
CP C
Check to see if the computed checksum in register C is the same as the checksum read from the cassette in Register A
030BH-030CH
If its the same, jump to 02E7H because the next instructions are for bad checksums
030DH-030EH
LD A,43H
Load Register A with a “C” character
030FH-0311H
LD (3C3EH),A
Display the “C” character in Register A on the video display (at 15422)
0312H-0313H
Jump to 02EAH and keep reading bytes

0314H-0316H – This routine reads two bytes from tape (providing that the tape is already running) and puts them in the HL register pair. It is used by the SYSTEM routine to read the last two bytes on tape which give the entry point. A JP (HL) can then be executed to jump to the location specified, when used for this purpose. Only HL is used by this routine.

0314H
“GETADR”
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (whichh reads one byte from the cassette drive specified in Register A, and returns the byte in Register A)
0317H
LD L,A
Load register L with the byte read from the cassette in Register A (which is the LSB of the 16 bit value)
0318H-031AH
Calls the READ ONE BYTE FROM CASSETTE routine at 0235H (whichh reads one byte from the cassette drive specified in Register A, and returns the byte in Register A)
031BH
LD H,A
Load register H with the byte read from the cassette in Register A (which is the MSB of the 16 bit value)
031CH
RET
Return
031DH
“SYSGO”
EX DE,HL
Load register pair DE with the input buffer pointer in register pair HL
031EH-0320H
LD HL,(40DFH)
Load register pair HL with the current execution address (which is stored at 40DFH).
Note: 40DFH-40E0H holds Used by DOS
0321H
EX DE,HL
So that we can run a RST 10H in the next instruction, we need to exchange the execution address in register pair HL with the input buffer pointer in register pair DE
0322H
Since we need to bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-Register And clears the CARRY flag if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
0323H-0325H
Call the ASCII TO INTEGER routine at 1E5AH.
NOTE:
  • The routine at 1E5A converts the ASCII string pointed to by HL to an integer deposited into DE. If the routine finds a non-numerica character, the conversion is stopped
0326H-0327H
Jump if it turns out there weren’t any digits in the input
0328H
EX DE,HL
Since there were digits (or else we would have jumped in the prior instruction), exchange the input buffer pointer in register pair HL with the execution address in register pair DE
0329H
Jump to the execution address (i.e. “/xxxx”) which is in register pair HL

032AH-0347H – OUTPUT ROUTINE
“OUTCHR”

  • This is a general purpose output routine which outputs a byte from the A register to video, tape or printer. In order to use it, the location 409CH must be loaded with -1 for tape, 0 for video or 1 for the line printer.
    Note: 409CH holds the current output device flag: -1=cassette, 0=video and 1=printer.
  • This routine outputs a byte to device determined by byte stored at (409CH) – FFH=Tape, 0=Video, l=Printer. When calling, A = output byte. Uses AF. Warning: This routine CALLs a Disk BASIC link at address 41ClH which may have to be “plugged” with a RETurn (C9H) instruction.
032AH
“DSPCHR”
PUSH BC
We are going to need to use Register C, so push register pair BC into the stack
032BH
LD C,A
Load register C with the character to be output in Register A
032CH-032EH
Go call the DOS link at 41ClH.
In NEWDOS 2.1, this writes to the system output device
032FH-0331H
LD A,(409CH)
Load Register A with the current output device number stored in 409CH.
Note: 409CH holds the current output device flag: -1=cassette, 0=video and 1=printer
0332H
OR A
Since LD doesn’t set flags, in order to be able to test Register A using flags we need to execute an OR A first. This will enable us to set the flags according to the current output device number in Register A
0333H
LD A,C
Load Register A with the character to be output in register C
0334H
POP BC
Get the value from the stack and put it in register pair BC

At this point, A is either +1, -1, or 0. The ROM handles this by testing for a positive number (1 = Cassette), and then a non-zero number (-1 = Printer), and then flows down (0 = Display) if neither of those apply.

0335H-0337H
If the value of the current output device number is positive it means CASSETTE, so jump to the the WRITE ONE BYTE TO CASSETTE routine at 0264H (which writes the byte in the A register to the cassette drive selected in the A register)
0338H-0339H
Jump to 039CH if the character in Register A is to be sent to the printer

033AH-0347H – “CRTOUT” OUTPUT ROUTINE

  • To use a ROM call to print a single character at the current cursor position, and to update the cursor position, load the ASCII value of the character into the A Register And then CALL 033AH.
  • To display special functions using a ROM call, load the A register with the value given below for the special function and then CALL 033AH.
    1. Backspace and erase previous character – 08H
    2. Carriage return and linefeed – 0DH
    3. Turn on cursor – 0EH
    4. Turn off cursor – 0FH
    5. Convert to 32 characters per line mode – 17H
    6. Backspace cursor – 18H
    7. Advance cursor one position – 19H
    8. Downward line feed – 1AH
    9. Upward line feed – 1BH
    10. Home (cursor to upper left corner) – 1CH
    11. Move cursor to beginning of current line – 1DH
    12. Erase from cursor position to end of line – 1EH
    13. Erase from cursor position to end of screen – 1FH
033AH
“CRTOUT”
PUSH DE
If we’re here, then that value in A wasn’t going to the cassette or the printer, so it must be going to the video. This routine performs the same function as 33H except that it doesn’t destroy the contents of the DE register pair. This means that all the general purpose registers are saved, which is often desirable.

Save the value in register pair DE on the stack
033BH-033DH
Call the DISPLAY A CHARACTER routine at 0033H (which puts the character in Register A on the video screen)
033EH
PUSH AF
Save the character in Register A on the stack
033FH-0341H
Go update the current cursor position and test to see if the display memory is full
0342H-0344H
LD (40A6H),A
Save the current cursor line position stored in 40A6H to Register A.
Note: 40A6H holds the current cursor line position
0345H
POP AF
Get the character from the stack and put it in Register A
0346H
POP DE
Get the value from the stack and put it in register pair DE
0347H
RET
Return

0348H-0357H – VIDEO ROUTINE

0348H-034AH
LD A,(403DH)
Load Register A with the contents of 403DH, which contains, among other things, the screen resolution (32 or 64 wide; Bit 3) the tape relay on/off instruction (Bit 2) and the positive/negative audio pulses (Bits 0-1).
Note: 403DH-4040H is used by DOS
034BH-034CH
AND 08H
Mask Register A against 00001000 to isolate Bit 3 (the 32/64 character per line flag) in Register A
034DH-034FH
LD A,(4020H)
Load Register A with the LSB of the current cursor position.
Note: 4020H-4021H holds Video DCB – Cursor location
0350H-0351H
If Bit 3 of 403DH was a zero, then we have 64 characters per line mode so JUMP down a few instructions to skip over the division needed to drop everything by half to 32 character mode
0352H
RRCA
Divide the LSB of the current cursor position in Register A by two
0353H-0354H
AND 1FH
Mask the cursor line position in Register A for 32 character per line (AND against 0001 1111) to force its position to be no less than 3C00H
0355H-0356H
AND 3FH
Mask the cursor line position in Register A for 64 characters per line (AND against 0011 1111) to force its position to be no more than 3FFFH
0357H
RET
Return

0358H-0360H – KEYBOARD ROUTINE
Here is the routine to simulate the INKEY$ function. It performs exactly the same function as 2BH but it restores all registers, whereas 2BH destroys the contents of the DE register pair. This makes 35BH more useful than 2BH.

0358H-035AH
“KBD2”
Go call the DOS link at 41C4H
035BH
PUSH DE
Since the next routine uses DE, save the value in register pair DE on the stack
035CH-035EH
Call the SCAN KEYBOARD routine at 002BH
035FH
POP DE
Get the value from the stack and put it in register pair DE
0360H
RET
Return

0361H-0383H – INPUT ROUTINE
“KIBUFF”

  • This is one of the general purpose input routines (see 5D9 and 1BB3 also). This routine inputs a string from the keyboard, up to a maximum of 240 characters (F0H), and echoes them to the screen. It puts this data into a buffer located at the address pointed to by the buffer pointer at 40A7H. (e.g. If 40A7H contains 5000H the data will be stored from 5000H onwards). The string is terminated with a zero byte. The program returns from this routine as soon as the ENTER key has been pressed. When it does so, HL contains the start address of the input string and B contains the length of the string. (RST 10H can be used to make HL point to the first character of the string, if required.).
    Note: 40A7H-40A8H holds the input Buffer pointer.
0361H
“LINP2”
XOR A
Zero Register A
0362H-0364H
LD (4099H),A
Save the value in Register A as the last key pressed (which is stored in 4099H).
Note: 4099H holds the Last key pressed
0365H-0367H
LD (40A6H),A
Save the value in Register A as the current cursor line position (which is stored in 40A6H).
Note: 40A6H holds the current cursor line position
0368H-036AH
Go call the DOS link at 41AFH.
In NEWDOS 2.1, this is the satrt of keyboard input
036BH
PUSH BC
Save register pair BC on the stack
036CH-036EH
LD HL,(40A7H)
Load register pair HL with the starting address of the input buffer (which is stored in 40A7H).
Note: 40A7H-40A8H holds the input Buffer pointer
036FH-0370H
LD B,0F0H
Load Register B with the length of the input buffer (which is 240)
0371H-0373H
“WAIT FOR NEXT LINE” keyboard input routine at 05D9H (which takes keyboard entry until a carriage return, a break, or buffer overrun occurs)
0374H
PUSH AF
Save the flags on the stack
0375H
LD C,B
Load register C with the length of the input in Register B
0376H-0377H
LD B,00H
Zero Register B so that register pair BC will have the length of the input
0378H
ADD HL,BC
Add the length of the input in register pair BC to the starting address of the input buffer in register pair HL
0379H-037AH
LD (HL),00H
Save an end of the input character at the location of the end of input pointer in register pair HL
037BH-037DH
LD HL,(40A7H)
Load register pair HL with the starting address of the input buffer (which is 40A7H).
Note: 40A7H-40A8H holds the input Buffer pointer
037EH
POP AF
Get the flags from the stack
037FH
POP BC
Get the value from the stack and put it in register pair BC
0380H
DEC HL
Decrement the input buffer pointer in register pair HL (so that HL is the input area pointer – 1)
0381H
RET C
Return if the BREAK key was pressed
0382H
XOR A
Otherwise (i.e., the BREAK key was not pressed), zero all the status flags
0383H
RET
Return

0384H-038AH – KEYBOARD ROUTINE

  • Waits for keypress
0384H-0386H
“KBWT2”
Go scan the keyboard
0387H
OR A
Check to see if a key was pressed
0388H
RET NZ
Return if a key was pressed (meaning OR A was set to NZ)
0389H-038AH
Loop until a key is pressed

038BH-039BH – PRINTER ROUTINE

  • This routine resets device type flag at 409CH to zero (output to video display), also outputs a carriage return to the line printer if printer is not at beginning of line (determined by checking the contents of the printer line position flag at 409BH – if flag contains zero, printer is at start of line). Note that if printer line position flag does not contain zero and the printer is not on line, the computer will “hang up” waiting for a “printer ready” signal.
038BH
XOR A
Zero Register A, which then means it contains the device code for VIDEO
038CH-038EH
LD (409CH),A
Save the value in Register A (the current output device code of video) to 409CH.
Note: 409CH holds the current output device flag: -1=cassette, 0=video and 1=printer
038FH-0391H
LD A,(409BH)
Load Register A with the current printer carriage position (which is stored at 409BH).
Note: 409BH holds the printer carriage position
0392H
OR A
Set the flags for the carriage position in Register A
0393H
RET Z
Return if the carriage position in Register A is equal to zero
0394H-0395H
LD A,0DH
Load Register A with a “CARRIAGE RETURN
0396H
PUSH DE
Save the value in register pair DE on the stack
0397H-0399H
Go send the carriage return character in Register A to the printer
039AH
POP DE
Get the value from the stack and put it in register pair DE
039BH
RET
Return

039CH-03C1H – PRINTER ROUTINE

  • This is the LPRINT routine. All registers are saved. The byte to be printed should be in the A register.
039CH
PUSH AF
Save the value in register pair AF on the stack
039DH
PUSH DE
Save the value in register pair DE on the stack
039EH
PUSH BC
Save the value in register pair BC on the stack
039FH
LD C,A
Load register C with the character to be sent to the printer in Register A
03A0H-03A1H
LD E,00H
Zero register E (which will ultimately hold the new character/line count of 0CH, 0DH, or 0AH)
03A2H-03A3H
CP 0CH
Check to see if the character to be sent to the printer in Register A is equal to 0CH (which is ‘skip to next line’)
03A4H-03A5H
Jump to 03B6H if the character to be sent to the printer in Register A is equal to 0CH
03A6H-03A7H
CP 0AH
Check to see if the character to be sent to the printer in Register A is a line feed character (i.e., 0AH)
03A8H-03A9H
Jump to 03ADH if the character to be sent to the printer in Register A isn’t a line feed character
03AAH-03ABH
LD A,0DH
Load Register A with a carriage return character (i.e., 0DH)
03ACH
LD C,A
Load register C with the character to be sent to printer in Register A
03ADH-03AEH
CP 0DH
Check to see if the character to be sent to the printer in Register A is a carriage return character
03AFH-03B0H
Jump to 03B6H if the character to be sent to the printer in Register A is a carriage return character
03B1H-03B3H
LD A,(409BH)
Load Register A with the current printer carriage position (stored in 409BH).
Note: 409BH holds the printer carriage position
03B4H
INC A
Increment the current carriage position in Register A
03B5H
LD E,A
Load register E with the current carriage position in Register A
03B6H
LD A,E
Load Register A with the current carriage position in register E. Why do this since its obviously already done? Becasuse this is a jump point!
03B7H-03B9H
LD (409BH),A
Save the current carriage position (which is stored in 409BH) in Register A.
Note: 409BH holds the printer carriage position
03BAH
LD A,C
Load Register A with the character to be sent to the printer in register C
03BBH-03BDH
Call the PRINT CHARACTER routine at 003B (which sends the character in the C register to the printer)
03BEH
POP BC
Get the value from the stack and put it in register pair BC
03BFH
POP DE
Get the value from the stack and put it in register pair DE
03C0H
POP AF
Get the value from the stack and put it in register pair AF
03C1H
RET
Return

03C2H-03E2H – DRIVER ENTRY ROUTINE

  • This routine is called from a RST 14 (with a device code of 01H in Register B), RST 1C (with a device code of 02H in Register B), and RST 24 (with a device code of 04H in Register B).
  • On entry, BC shoud contain the Device Control Block and A may contain (if needed) the output control/data
03C2H
PUSH HL
Save register pair HL on the stack
03C3H-03C4H
PUSH IX
Save the value in register pair IX on the stack
03C5H
PUSH DE
Save the starting address of the device control block in register pair DE on the stack
03C6H-03C7H
POP IX
Get the starting address of the device control block from the stack and put it in register pair IX
03C8H
PUSH DE
Save the value in register pair DE on the stack
03C9H-03CBH
LD HL,03DDH
Load register pair HL with a return address of 03DDH
03CCH
PUSH HL
Save the return address in register pair HL on the stack
03CDH
LD C,A
Save the character to output (current held in Register A) to register C so we can use Register A
03CEH
LD A,(DE)
Load Register A with the device type code (stored the memory location pointed to by DE)
03CFH
AND B
Isolate the device code bits in A by AND’ing with the device codes in B
03D0H
CP B
Check to see if the updated device type code in Register A is the same as the driver entry code in Register B
03D1H-03D3H
Jump to the DOS exit link at 4033H if the updated device type code in Register A isn’t the same as the driver entry code in Register B
03D4H-03D5H
CP 02H
At this point we know that the updated device type code in A is the same as the driver code entry, so let’s move on. First, reset the flags
03D6H-03D8H
LD L,(IX+01H)
Load register L with the LSB of the driver entry address at the location of the device control block pointer in register pair IX plus one
03D9H-03DBH
LD H,(IX+02H)
Load register H with the MSB of the driver entry address at the location of the device control block pointer in register pair IX plus one
03DCH
Jump to the driver entry address in register pair HL
03DDH
POP DE
Get the value from the stack and put it in register pair DE
03DEH-03DFH
POP IX
Get the value from the stack and put it in register pair IX
03E0H
POP HL
Get the value from the stack and put it in register pair HL
03E1H
POP BC
Get the value from the stack and put it in register pair BC
03E2H
RET
Return

03E3H-0457H – KEYBOARD DRIVER

  • This is the keyboard driver. It scans the keyboard and converts the bit pattern obtained to ASCII and stores it in the A register.
03E3H-03E5H
LD HL,4036H
Load register pair HL with the keyboard work area’s starting address (which is 4036H).
Note: 4036H-403CH is the keyboard work area
03E6H-03E8H
LD BC,3801H
Load register pair BC with the keyboard memory’s starting address (which is 3801H)
03E9H-03EAH
LD D,00H
Zero register D, which will be used to track the keyboard code.
03EBH
LD A,(BC)
Load Register A with the value at the location of the keyboard memory pointer in register pair BC (which is row N)
03ECH
LD E,A
Load register E with the keyboard memory value in Register A (8 column bits)
03EDH
XOR (HL)
Check for inequality by XORing the value at the location of the keyboard work area pointer in register pair HL with the keyboard memory value in Register A
03EEH
LD (HL),E
Save the keyboard memory value (the column bits) in register E at the location of the keyboard work area pointer in register pair HL
03EFH
AND E
Test for the active row by masking the adjusted value in Register A with the value at the location of the keyboard work area pointer in register pair HL
03F0H-03F1H
Jump to 03FAH if the new key pressed is in row N
03F2H
INC D
Increment the keyboard row counter in register D
03F3H
INC L
Increment the keyboard work area pointer in register pair HL
03F4H-03F5H
RLC C
Adjust the keyboard memory pointer in register pair BC by stepping it from 3801 to 3840 by rotating the bits left (RLC)
03F6H-03F8H
Jump to 03EBH if the whole of keyboard memory hasn’t been checked (by POSITIVE bit [Bit 7] being on). This has the effect of looping over the first 6 rows of the keyboard but NOT doing row 7, which has the shift key
03F9H
RET
Return
03FAH
LD E,A
Save the column number in Register A in register E
03FBH
LD A,D
Load Register A with the row counter in register D (this is going to cycle from 0 through 6)
03FCH
RLCA
Multiply the row counter in Register A by two
03FDH
RLCA
Multiply the row counter in Register A by two
*03FBH-03FDH
JP 011CH
For ROM v1.2, jump to the new keyboard debounce routine. That routine includes the now deleted RCLA, RCLA instructions which had to be killed to make room for this 3 byte jump opcode
03FEH
RLCA
Multiply the row counter in Register A by two
03FFH
LD D,A
Load register D with the row counter in Register A
0400H-0401H
LD C,01H
Load register C with the starting column counter (as bit 0)
0402H
LD A,C
Load Register A with the column counter in register C (as a mask)
0403H
AND E
Check to see if the column counter in Register A is the same as the active column number in register E
0404H-0405H
Jump to 040BH if the column counter in Register A is the same as the active column number in register E
0406H
INC D
Increment the column number (which is held in register D)
0407H-0408H
RLC C
Adjust the column counter in register C left 1 bit to align the mask
0409H-040AH
Loop back to 0402H until the value in register D is adjusted for its column

040BH – We now have identified the key. Next we need to see if it is shifted.

040BH-040DH
LD A,(3880H)
Load Register A with the value of the SHIFT but from memory location 3880H
040EH
LD B,A
Load Register B with the SHIFT FLAG value in Register A
040FH
LD A,D
Load Register A with the value in register D (Row * 8 + column 0-7)
0410H-0411H
ADD 40H
Adjust the ASCII value in Register A (Row * 8 + column (0-7) + 64 decimal)
0412H-0413H
CP 60H
Check to see if the value in Register A is alphabetic by testing for the 4 rows (@, A-Z)
0414H-0415H
Jump to 0429H if the value in Register A is nonalphabetic
0416H-0417H
RRC B
Put the SHIFT value in Register B in the carry flag (as the RRC command rotates right, and puts bit 0 into the carry bit)
0418H-0419H
Jump if the SHIFT key wasn’t pressed (i.e., the rotated right Register B’s bit zero wasn’t a zero)
041AH-041BH
ADD 20H
Adjust the value in Register A for lower case (by ANDing it against 0010 0000)
041CH
LD D,A
Load register D with the adjusted character in Register A
041DH-041FH
LD A,(3840H)
Load Register A with the value at keyboard memory row six (which is 14400)
0420H-0421H
AND 10H
Check to see if the down arrow key (or ENTER) was pressed (by ANDing it against 0001 0000)
0422H-0423H
Jump to 044CH if down arrow (or ENTER) wasn’t pressed
0424H
LD A,D
Load Register A with the character in register D
0425H-0426H
SUB 60H
Adjust the value of the character in Register A down by 96, possibly to make it a CONTROL KEY
0427H-0428H
Jump to 044BH

0429H – If we are here, the character was not alpha numeric, so need to check for special and/or shift.

0429H-042AH
SUB 70H
Adjust the value of the character in Register A down by 112 (for a special key, like ENTER or SPACE)
042BH-042CH
Jump to 043DH if the character in Register A is for keyboard row six
042DH-042EH
ADD 40H
Readjust the value of character in Register A by adding 64 to adjust to rows 4-5
042FH-0430H
CP 3CH
Check to see if the character in Register A is a 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, “:”, “;”, or “,” ,character
0431H-0432H
Jump to 0435H if the character in Register A is one of those characters
0433H-0434H
XOR 10H
Adjust the character in Register A by XORing against 0001 0000 to invert bit 5
0435H-0436H
RRC B
Put the SHIFT value in Register B into the Carry flag
0437H-0438H
Jump to 044BH if the SHIFT key wasn’t pressed
0439H-043AH
XOR 10H
Adjust the character in Register A by XORing against 0001 0000 to reinvert bit 5
043BH-043CH
Jump to 044BH to output
043DH
RLCA
Adjust the value in Register A to be (ROW*8 + COLUMN-48) * 2)
043EH-043FH
RRC B
Put the SHIFT value in Register B into the Carry flag
0440H-0441H
Jump to 0443H if the SHIFT key wasn’t pressed
0442H
INC A
Increment the value in Register A to turn (ROW*8 + COLUMN-48) * 2) into (COLUMN*2+1)
0443H-0445H
LD HL,0050H
Load register pair HL with the starting address of the keyboard lookup table at 50H, which is the last row
0446H
LD C,A
Load register C with the offset in Register A (which is either 43D or 442)
0447H-0448H
LD B,00H
Zero Register B
0449H
ADD HL,BC
Add the offset in register pair BC to the starting address of the keyboard lookup table in register pair HL
044AH
LD A,(HL)
Load Register A with the ASCII value at the location of the keyboard lookup table pointer in register pair HL
044BH
LD D,A
Load register D with the ASCII value for the key pressed in Register A
044CH-044EH
LD BC,0DACH
Load register pair BC with the delay count (which is 3500)
044FH-0451H
Call the delay routine at 0060H (which will delay BC times 14.65)
0452H
LD A,D
Load Register A with the ASCII value for the key pressed (saved in Register D)
0453H-0454H
CP 01H
Check to see if the BREAK key was pressed
0455H
RET NZ
Return if the BREAK key wasn’t pressed
0456H
RST 28H
If the BREAK key was pressed,call the DOS FUNCTION CALL routine at RST 28 (which passes request code in A-register to DOS for processing. Returns for non-disk system. For disk systems, the A register must contain a legitimate DOS function code. If the code is positive, the CALL is ignored and control returns to the caller. Note that the DOS routine discards the return address stored on the stack by the RST instruction. After processing control will be returned to the previous address on the stack)
0457H
RET
Return

0458H-058CH – VIDEO DRIVER

  • This is the video driver. On entry, the character to be displayed should be in the C register. On exit, A would contain the character at the cursor (if called for an INPUT). This routine handles scrolling etc.
    Register IX points to the DCB, so IX+0 = the DCB type, IX+1 = LSB of the Driver Address, IX+2 = MSB of the Driver Address, IX+3 = LSB of the Cursor Position, IX+4 = MSB of the Cursor Position, IX+5 = Cursor Character, IX+6 = “D”, and IX+7=”O”
0458H-045AH
“DSP”
LD L,(IX+03H)
Load register L with the LSB of the current cursor position at the location of the video device control block pointer in register pair IX plus three
045BH-045DH
LD H,(IX+04H)
Load register H with the MSB of the current cursor position at the location of the video device control block pointer in register pair IX plus four
045EH-045FH
Jump to 049AH if get last character
0460H-0462H
LD A,(IX+05H)
Load Register A with the cursor on/off flag (which is stored at the location of the video device control block pointer in register pair IX plus five)
0463H
OR A
Check to see if the cursor is on or off
0464H-0465H
Jump to 0467H if the cursor is off
0466H
LD (HL),A
Display the character in Register A at the location of the current cursor position in register pair HL since the cursor is on
0467H
“DSPGRP”
LD A,C
Load Register A with the character to be displayed from Register C
0468H-0469H
CP 20H
Check to see if the character to be displayed in Register A is a control code
046AH-046CH
Since CP returns C set if Register A (the character to be displayed) is less than the test value (20H; meaning it is a control character below SPACE), jump to 0506H if the character to be displayed in Register A is a control code
046DH-046EH
CP 80H
Check to see if the character to be displayed in Register A is a graphic character or space compression code
046FH-0470H
Since CP returns NC set if Register A (the character to be displayed) is greater than or equal to the test value (80H; meaning it is a graphic character or higher), jump to 04A6H if the character to be displayed in Register A is a graphic character or space compression code
0471H-0472H
CP 40H
Check to see if the character to be displayed in Register A is an alphabetic character
0473H-0474H
Since CP returns C set if Register A (the character to be displayed) is less than the test value (40H; meaning it is below the “@”), jump to 047DH if the character to be displayed in Register A is a nonalphabetic character
0475H-0476H
SUB 40H
If we are still here, then the character in Register A is between 40H (“@”) and 7FH (the last character before the graphics). Drop this down 40H.
0477H-0478H
CP 20H
Check to see if the character to be displayed in Register A is a lower case character
0479H-047AH
Since CP returns C set if Register A (the newly subtracted character) is less than the test value (20H or 32), jump to 047DH since the character to be displayed in Register A isn’t lower case
047BH-047CH
SUB 20H
Convert the lower case character in Register A to upper case by subtracting 32
047DH-047FH
“DSPCHR”
Go to 0541H display the character in Register A (and scroll the screen if necessary)
0480H
“DSPSKP”
LD A,H
Load Register A with the MSB of the current cursor position in register H
0481H-0482H
AND 03H
Mask the value in Register A so that it will be in the range of video memory (3C00H-3FFFH) by ANDing it against 0000 0011
0483H-0484H
OR 3CH
Force the MSB of the buffer to be 3C-3Fh (i.e., video memory) by ORing it against 0011 1100
0485H
LD H,A
Load register H with the updated MSB value (which was forced to be within video memory) in Register A
0486H
LD D,(HL)
Load register D with the value at the location of the current cursor position in register pair HL
0487H-0489H
LD A,(IX+05H)
Load Register A with the cursor on/off flag at the location of the video device control block pointer in register pair IX plus five
048AH
OR A
Check to see if the cursor is on or off
048BH-048CH
Jump to 0492H if the cursor is off
048DH-048FH
LD (IX+05H),D
Since the cursor is on, save the character being displayed in register D as the cursor on/ off flag at the location of the video device control block pointer in register pair IX plus five
0490H-0491H
LD (HL),5FH
Display the cursor character (of 5FH) at the current location of the cursor in register pair HL
0492H-0494H
LD (IX+03H),L
Save the LSB of the current cursor position in register L at the location of the video device control block in register pair IX plus three
0495H-0497H
LD (IX+04H),H
Save the MSB of the current cursor position in register H at the location of the video device control block in register pair IX plus four
0498H
LD A,C
Load Register A with the character that was displayed in register C
0499H
RET
Return

049AH – Read the character at the current position of the display.

049AH-049CH
“DSPRD”
LD A,(IX+05H)
Load Register A with the cursor on/off flag
049DH
OR A
Check to see if the cursor is on or off
049EH
RET NZ
Return if the cursor is on
049FH
LD A,(HL)
If the cursor is off, show the character it was hiding instead by loading Register A with the character at the location of the current cursor position in register pair HL
04A0H
RET
Return

04A1H – Go to the beginning of the line.

04A1H
“DSPBOL”
LD A,L
Load Register A with the LSB of the current position in register L
04A2H-04A3H
AND 0C0H
Point to the beginning of the line by ANDing it against 1100 0000 to remove the lowest 6 bits (so it will be XX00H, XX40H, XX80H, or XXC0H). This is the same thing as a CARRIAGE RETURN but without the associated LINE FEED
04A4H
LD L,A
Load register L with the updated value in Register A
04A5H
RET
Return with the new video buffer address stored in HL

04A6H – Handle graphic characters.

04A6H-04A7H
“DSPGRC”
CP C0H
Check to see if the character to be displayed in Register A is a space compression character
04A8H-04A9H
Since CP returns C set if Register A (the character to be displayed) is less than the test value (C0H; meaning it is below the space compression characters or, another way, is a graphic character), jump to 047DH if the character to be displayed in Register A isn’t a space compression character (which means it is a graphic character)
04AAH-04ABH
SUB C0H
Now we know we have a space compresison code, so adjust the value in Register A so that it will hold the number of spaces to be displayed
04ACH-04ADH
Jump to 0480H if there aren’t any spaces to be displayed
04AEH
LD B,A
Now we know it is a space compression character and that at least one space is to be displayed, so load Register B with the number of spaces to be displayed in Register A (since the space compression codes are sequential from 0C0H up)
04AFH-04B0H
LD A,20H
Load Register A with a space character
04B1H-04B3H
Gosub to 0541H to display the blank character in Register A (and scroll the screen if necessary)
04B4H-04B5H
Loop back to 04AFH until all of the spaces have been displayed
04B6H-04B7H
Once all the spaces have been displayed, jump to 0480H

04B8H – Turn the cursor on.

04B8H
“DSPCON”
LD A,(HL)
Load Register A with the character being displayed at the location of the current cursor position in register pair HL
04B9H-04BBH
“DSPCUR”
LD (IX+05H),A
Save the value in Register A as the cursor on/off flag at the location of the video device control block pointer in register pair IX plus five
04BCH
RET
Return

04BDH – Turn the cursor off.

04BDH
“DSPCOF”
XOR A
Zero Register A to turn the cursor flag off
04BEH-04BFH
Jump to 04B9H to put a 0 into (IX+05H) and RETurn

04C0H – Home the cursor

04C0H-04C2H
“DSPHOM”
LD HL,3C00H
Load register pair HL with the starting address of video memory (which is 3C00H)
04C3H-04C5H
LD A,(403DH)
Load Register A with the contents of 403DH, which contains, among other things, the screen resolution (32 or 64 wide; Bit 3) the tape relay on/off instruction (Bit 2) and the positive/negative audio pulses (Bits 0-1).
Note: 403DH-4040H is used by DOS
04C6H-04C7H
AND 0F7H
Mask Register A against 1111 0111, forcing Bit 3 to OFF to denote 64 characters per line.
04C8H-04CAH
LD (403DH),A
Put the masked Register A back into 403DH.
04CBH-04CCH
OUT (0FFH),A
Send the value in Register A out port 255 which is the video/cassette port
04CDH
RET
Return

04CEH – Backspace

04CEH
“DSPBSP”
DEC HL
Decrement the current cursor position (i.e., backspace) in register pair HL
04CFH-04D1H
LD A,(403DH)
Load Register A with the 32/64 character per line flag (which is at 403DH).
Note: 403DH-4040H is used by DOS
04D2H-04D3H
AND 08H
Check to see if it’s 32 or 64 characters per line by ANDing it against 0000 1000
04D4H-04D5H
Since the AND leaves us with either a 0 (64 characters per line) or a 1 (32 characters per line), jump to 04D7H if it’s 64 characters per line
04D6H
DEC HL
Right now we know it is 32 characters per line (since we didn’t jump away), so we need to backspace AGAIN by decrementing the current cursor position in register pair HL
04D7H-04D8H
“DSPBS2”
LD (HL),20H
Display a space character at the location of current cursor position in register pair HL
04D9H
RET
Return

04DAH – Cursor Left

04DAH-04DCH
“DSPLFT”
LD A,(403DH)
Load Register A with the 32/64 character per line flag (which is at 403DH).
Note: 403DH-4040H is used by DOS
04DDH-04DEH
AND 08H
Mask Register A against 0000 1000 to isolate Bit 3 and set the flags Z and NZ based on that bit
04DFH-04E1H
If Bit 3 was not zero then we have 32 characters per line, so GOSUB to 04E2H. Note: This is a little trick. By doing a GOSUB to the next line, you effectively block the RET at the end of the routine from jumping out, and instead it jumps back here; thus running the routine TWICE
04E2H
LD A,L
We are actually here regardless of what Bit 3 was. Load Register A with the LSB of the current cursor position in register L
04E3H-04E4H
AND 3FH
Mask the value in Register A by ANDing it against 0011 1111 to backspace LSB of curstor to the previous line and then …
04E5H
DEC HL
Backspace the cursor by 1 by decrementing the current cursor position in register pair HL
04E6H
RET NZ
Return if still on the same line

04E7H – Cursor Down. This is a space saver because if the cursor isn’t on the same line it needs to move down, so jumping here is also jumping to a CURSOR DOWN routine that was simply a fall-through from a wrap around.

04E7H-04E9H
LD DE,0040H
We know we are not on the same line anymore so load register pair DE with the length of a line on the video display (which is 64)
04EAH
ADD HL,DE
Skip down 1 line by adding the length of a line on the video display in register pair DE to the current cursor position in register pair HL
04EBH
RET
Return

04ECH – Cursor Right

04ECH
“DSPRHT”
INC HL
Increment the current cursor position in register pair HL
04EDH
LD A,L
Load Register A with the LSB of the current cursor position in register L
04EEH-4EFH
AND 3FH
Check to see if the cursor is still on the same line via an overflow through ANDing it against 0011 1111
04F0H
RET NZ
Return if the cursor is still on the same line

04F1H – Cursor Up. Same trick as dealing with CURSOR DOWN if there was an overflow, this does a CURSOR UP if you back up too far.

04F1H-04F3H
“DSPUP”
LD DE,0FFC0H
Now we know the cursor is no longer on the same line, so we need to load register pair DE with a negative length of a line on the video display (which is -64)
04F4H
ADD HL,DE
Add the negative length of a line on the video display in register pair DE (i.e., -64) to the current cursor position in register pair HL
04F5H
RET
Return

04F6H – Set up 32-Character mode.

04F6H-04F8H
“DSPFTB”
LD A,(403DH)
This routine is going to change the display to 32 character mode so first we need to load Register A with the 32/64 character per line flag stored at 04F6H.
Note: 403DH-4040H is used by DOS
04F9H-04FAH
OR 08H
Adjust the value in Register A for 32 characters per line by ORing it against 0000 1000
04FBH-04FDH
LD (403DH),A
Save the resulting value in Register A back into 403DH (the 32/64 character per line flag).
Note: 403DH-4040H is used by DOS
04FEH-04FFH
OUT (0FFH),A
OUT (CASIO$),A
Send the value in Register A out the port 255 (the video/cassette)
0500H
INC HL
Increment the current cursor position in register pair HL
0501H
LD A,L
Load Register A with the LSB of the current cursor position in register L
0502H-0503H
AND 0FEH
Make the LSB value (in Register A) to be an even value (since we are in 32 character per line mode) by ANDing it against 1111 1110
0504H
LD L,A
Load register L with the updated value in Register A
0505H
RET
Return

0506H – Process control characters

0506H-0508H
“DSPCTL”
LD DE,0480H
LD DE,DSKSKP
Load register pair DE with the return address
0509H
PUSH DE
Save the return address in register pair DE on the stack
050AH-050BH
CP 08H
Check to see if the character in Register A is a backspace and erase character (i.e., 08H)
050CH-050DH
Since CP returns C set if Register A (the character to be displayed) is less than the test value (08H), jump to 04CEH as the character to be displayed in Register A is a backspace cursor and erase character
050EH-050FH
CP 0AH
Check to see if the character in Register A is less than a line feed character
0510H
RET C
Return if the character to be displayed in Register A is less than a line feed character so we can ignore them
0511H-0512H
CP 0EH
Check to see if the character to be displayed in Register A is less than or equal to a turn on the cursor character
0513H-0514H
Jump if the character to be displayed in Register A is less than a turn on the cursor character so that a carriage return will be displayed
0515H-0516H
Jump if the character to be displayed in Register A is a turn on the cursor character
0517H-0518H
CP 0FH
Check to see if the character in Register A is a turn off the cursor character
0519H-051AH
Jump if the character to be displayed in Register A is a turn off the cursor character
051BH-051CH
CP 17H
Check to see if the character to be displayed in Register A is a turn on the 32 character per line mode character
051DH-051EH
Jump if the character to be displayed in Register A is a turn on the 32 character per line mode character
051FH-0520H
CP 18H
Check to see if the character to be displayed in Register A is a left arrow character
0521H-0522H
Jump if the character to be displayed in Register A is a left arrow character
0523H-0524H
CP 19H
Check to see if the character to be displayed in Register A is a right arrow character
0525H-0526H
Jump if the character to be displayed in Register A is a right arrow character
0527H-0528H
CP 1AH
Check to see if the character to be displayed in Register A is a down arrow character
0529H-052AH
Jump if the character to be displayed in Register A is a down arrow character
052BH-052CH
CP 1BH
Check to see if the character to be displayed in Register A is an up arrow character
052DH-052EH
Jump if the character to be displayed in Register A is an up arrow character
052FH-0530H
CP 1CH
Check to see if the character to be displayed in Register A is a home the cursor character
0531H-0532H
Jump if the character to be displayed in Register A is a home the cursor character
0533H-0534H
CP 1DH
Check to see if the character to be displayed in Register A is a backspace to the beginning of the line character
0535H-0537H
Jump if the character to be displayed in Register A is a backspace to the beginning of the line character
0538H-0539H
CP 1EH
Check to see if the character to be displayed in Register A is an erase to the end of the line character
053AH-053BH
Jump if the character to be displayed in Register A is an erase to the end of the line character
053CH-053DH
CP 1FH
Check to see if the character to be displayed in Register A is an erase to the end of the screen character
053EH-053FH
Jump if the character to be displayed in Register A is an erase to the end of the screen character
0540H
RET
Return if the character to be displayed isn’t any of the above control codes
  • 0541H – This subroutine displays the character in Register A at the location HL and scrolls the screen if needed.
0541H
LD (HL),A
Put the character stored in A into the memory location stored in HL
0542H
INC HL
Increment the current cursor position in register pair HL
0543H-0545H
LD A,(403DH)
Load Register A with the 32/64 character per line flag (stored in 403DH).
Note: 403DH-4040H is used by DOS
0546H-0547H
AND 08H
Check to see if it’s 32 or 64 characters per line by ANDing it against 0000 1000
0548H-0549H
Jump to 054BH if it’s 64 characters per line
054AH
INC HL
Increment the current cursor position in register pair HL
054BH
LD A,H
Load Register A with the MSB of the current cursor position in register H
054CH-054DH
CP 40H
Check to see if the end of video memory plus one has been reached
054EH
RET NZ
Return if the end of video memory plus one hasn’t been reached
054FH-0551H
LD DE,FFC0H
Load register pair DE with a negative length of a line on the video display (i.e., -64)
0552H
ADD HL,DE
Move the pointer back 1 line by adding the negative length of a line on the video display in register pair DE to the current cursor position in register pair HL
0553H
PUSH HL
Save the current cursor position in register pair HL on the stack
  • To use a ROM call to scroll (shift the entire display upward one line), CALL 0553H.
0554H-0556H
LD DE,3C00H
Load register pair DE with the starting address of video memory
0557H-0559H
LD HL,3C40H
Load register pair HL with the starting address of the second line of the video memory
055AH
PUSH BC
Save the value in register pair BC on the stack
055BH-055DH
LD BC,03C0H
Load register pair BC with the length of video memory to be moved (which is 15 lines or 960 bytes)
055EH-055FH
LDIR
Move the last fifteen lines of video memory to the first fifteen lines of video memory to scroll 1 line
0560H
POP BC
Get the value from the stack and put it in register pair BC
0561H
EX DE,HL
Load register pair HL with the starting address of the sixteenth line of video memory
0562H-0563H
Jump forward to 057DH because a random block of code is now going to intervene because of need to share the code at 057DH (so the routine flows into it)

This code is jumped to by 0513H if it is determined that the character to be displayed in Register A is less than “turn on the cursor character” so that a carriage return will be displayed

0564H
LD A,L
Load Register A with the LSB of the current cursor position in register L
0565H-0566H
AND C0H
Adjust the value in Register A so that it’s the start of the current line by ANDing it with 1100 0000
0567H
LD L,A
Load register L with the updated value in Register A
0568H
PUSH HL
Save the current cursor position in register pair HL on the stack
0569H-056BH
LD DE,0040H
Load register pair DE with the length of a line on the video display (which is 40H or 64 Decimal)
056CH
ADD HL,DE
Add the length of a line on the video display in register pair DE to the current cursor position in register pair HL
056DH
LD A,H
Load Register A with the MSB of the current cursor position in register H
056EH-056FH
CP 40H
Check to see if the end of video memory plus one has been reached (which is 40H or 64 Decimal)
0570H-0571H
Jump to 0554H (to scroll the screen) if the end of video memory plus one has been reached
0572H
POP DE
Get the cursor position from the stack and put it in register pair DE
0573H
PUSH HL
Save the new cursor position in register pair HL on the stack
0574H
LD D,H
Load register D with the MSB of the current cursor position in register H
0575H
LD A,L
Load Register A with the LSB of the current cursor position in register L
0576H-0577H
OR 3FH
Isolate the screen line by masking the value in Register A by ORing it against 0011 1111
0578H
LD E,A
Save the updated value in Register A in register E
0579H
INC DE
Increment the adjusted cursor position in register pair DE
057AH-057BH
Jump forward to the line blanking code of 0580H
057CH
PUSH HL
Save the cursor position in register pair HL on the stack.

Clear to end of frame routine. To use this routine load the HL register pair with the screen address from which you want the erasing to start. The DE and A registers are used
  • To use a ROM call to clear the video screen from (including) position N – where N is an integer between 0 and 1023 (decimal), inclusive, to the end of the display, Load the HL register with the value 3C00H + N and then CALL 057CH.
057DH-057FH
LD DE,4000H
Load register pair DE with the end of video memory plus one (which is 4000H)
0580H-0581H
LD (HL),20H
Display a space (which is 20H) at the video memory pointer in register pair HL
0582H
INC HL
Increment the video memory pointer in register pair HL
0583H
LD A,H
Load Register A with the MSB of the video memory pointer held in register H
0584H
CP D
Check to see if the MSB of the video memory pointer in Register A is the same as the MSB of the ending memory pointer in register D
0585H-0586H
LOOP back to 0580H (display a space and move forward 1) if the MSB of the video memory pointer in Register A isn’t the same as the MSB of the ending memory pointer in register D
0587H
LD A,L
Load Register A with the LSB of the video memory pointer in register L
0588H
CP E
Check to see if the LSB of the video memory pointer in Register A is the same as the LSB of the ending memory pointer in register E
0589H-058AH
LOOP back to 0580H (display a space and move forward 1) if the LSB of the video memory pointer in Register A isn’t the same as the LSB of the ending memory pointer in register E
058BH
POP HL
Get the current cursor position from the stack and put it in register pair HL
058CH
RET
Return

058DH-0D8H – PRINTER DRIVER

  • LPRINT driver routine, handling printer I/O etc. The character to be printed should be in register C.
058DH
LD A,C
Load Register A with the character to be sent to the printer in register C
058EH
OR A
Set the status flags and test A to see if it is zero
058FH-0590H
Jump to 05D1H (get the printer status and return) if the character to be sent to the printer in Register A is equal to zero
0591H-0592H
CP 0BH
Check to see if the character to be sent to the printer in Register A is a skip to the top of the form character which is CHR$(11)
0593H-0594H
Jump to 059FH if the character to be sent to the printer in Register A is a skip to the top of the form character
0595H-0596H
CP 0CH
Check to see if the character to be sent to the printer in Register A is a conditional skip to the top of the form character which is CHR$(12)
0597H-0598H
Jump to 05B4H if the character to be sent to the printer in Register A isn’t a conditional skip to the top of the form character
0599H
XOR A
Zero Register A (which causes the null character to be printed)
059AH-059CH
OR (IX+03H)
Check to see if the number of lines per page at the location of the printer device control block pointer in register pair IX plus three is the same as the value in Register A
059DH-059EH
Jump to 05B4H if zero lines are to be skipped
059FH-05A1H
LD A,(IX+03H)
Load Register A with the number of lines per page at the location of the printer device control block in register pair IX plus three
05A2H-05A4H
SUB (IX+04H)
Subtract the lines printed so far at the location of the printer device control block pointer in register pair IX plus four from the number of lines per page in Register A
05A5H
LD B,A
A now has the number of lines to skip, so load B with with the number of lines to skip (since DJNZ loops based on B)
05A6H-05A8H
Call the GET PRINTER STATUS routine at 05D1H (which returns the status of the line printer in the status Register As 0 if the printer is ready, and otherwise with a reason code if not ready)
05A9H-05AAH
Loop bac to 05A6H until the printer is ready
05ABH-05ACH
LD A,0AH
Now the printer is ready and B has the number of lines to skip. Load Register A with a line feed character which is CHR$(10)
05ADH-05AFH
LD (37E8H),A
Send the value in Register A to the printer by loading it into memory location 37E8H
05B0H-05B1H
Loop back to 05A6H until all of the lines have been skipped
05B2H-05B3H
Now all the lines have been skipped, so jump to 05CCH to reset the line counter and return
05B4H
PUSH AF
Save the character to be sent to the printer in Register A on the stack
05B5H-05B7H
Call the GET PRINTER STATUS routine at 05D1H (which returns the status of the line printer in the status Register As 0 if the printer is ready, and otherwise with a reason code if not ready)
05B8H-05B9H
Loop back to 05B5H until the printer is ready
05BAH
POP AF
Get the character to be sent to the printer from the stack and put it in Register A
05BBH-05BDH
LD (37E8H),A
Send the character in Register A to the printer by putting the character into 37E8H
05BEH-05BFH
CP 0DH
Check to see if the character which was just sent to the printer was a carriage return
05C0H
RET NZ
If the character sent to the printer in Register A isn’t a carriage return, return out of the print routine
05C1H-05C3H
INC (IX+04H)
Now we know the printer just got a carriage return, so increment the number of lines printed so far at the location of the printer device control block pointer in register pair IX plus four
05C4H-05C6H
LD A,(IX+04H)
Load Register A with the number of lines printed so far at the location of the printer device control block pointer in register pair IX plus four
05C7H-05C9H
CP (IX+03H)
Check to see if the number of lines printed so far in Register A is the same as the number of lines per page at the location of the printer device control block pointer in register pair IX plus three
05CAH
LD A,C
Load Register A with the character sent to the printer in register C
05CBH
RET NZ
Return if the number of lines printed so far isn’t the same as the number of lines per page
05CCH-05CFH
LD (IX+04H),04H
Zero the number of lines printed so far at the location of the printer device control block pointer in register pair IX plus four
05D0H
RET
Return

05D1H – Get printer status routine.

  • A call to 05D1 will return the status of the line printer in the status Register As 0 if the printer is ready/selected, and non-zero if not ready, as follows:
    • Bit 7 = Printer Busy. 1=Busy
    • Bit 6 = Paper Status. 1= Out of paper.
    • Bit 5 = Printer Ready. 1 = Ready.
    • All other bits are not used.
05D1H-05D3H
LD A,(37E8H)
Get the status value from the printer (which is held in 37E8H) and put it in Register A
05D4H-05D5H
AND F0H
Since only bits 7, 6, and 5 are used, mask out the rest of Register A by ANDing it against 1111 0000
05D6H-05D7H
CP 30H
Check to see if the printer is ready by comparing the ANDed value against 0011 0000 (which isolates bits 5 and 4, so the result is either ZERO if they are set or anything else if they are not)
05D8H
RET
Return

05D9H-0673H – ACCEPT KEYBOARD INPUT ROUTINE
“KLINE”

  • This is the most basic of the string input routines and is used by the two others (1BB3H and 0361H) as a subroutine. To use it, load HL with the required buffer address and the B register with the maximum buffer length required. Keyboard input over the specified maximum buffer length is ignored, and after pressing the (ENTER) key it will return with HL containing the original buffer address and B with the string length.
    A call to this memory location Accepts keyboard input and stores each character in a buffer supplied by caller. Input continues until either a carriage return or a BREAK is typed, or until the buffer is full. All edit control codes are recognized, e.g. TAB, BACKSPACE, etc.
    On exit the registers contain: HL=Buffer address, B=Number of characters transmitted excluding last, C=Orginal buffer size, A=Last character received if a carriage return or BREAK is typed. Carry Set if break key was terminator, reset otherwise. If the buffer is full, the A register will contain the buffer size.
  • To use a ROM call to accept a restricted number of keyboard characters for input (n), use:
    LD HL,(40A7H)
    LD B,n
    CALL 05D9H

    Up to n characters will be accepted, after which the keyboard will simply be ignored until the ENTER (or LEFT ARROW, or BREAK, or CLEAR) key is pressed. These characters will be stored in consecutive memory cells starting at the address contained in 40A7H-40A8H (the keyboard buffer area), with a 0DH (carriage return) byte at the end. Upon completion, the HL register pair will contain the address of the first character of the stored input, and the B register will contain the number of characters entered. NOTE: No “?” is displayed as a result of the execution of the above program. If the “?” display is desired to prompt the typing of the input, precede the above program segment with:
    LD A,3FH
    CALL 033AH
    LD A,20H
    CALL 033AH
05D9H
“LINP1”
PUSH HL
Save the start of the input buffer area pointer in register pair HL on the stack
05DAH-05DBH
LD A,0EH
Load Register A with a turn on the cursor character (which is 14)
05DCH-05DEH
Display a cursor by calling the DISPLAY A CHARACTER routine at 0033H (which puts the character in Register A on the video screen)
05DFH
LD C,B
Load register C with the size of the input buffer in Register B
05E0H-05E2H
Call the “WAIT FOR KEYBOARD INPUT” routine at 0049H, so as to wait until a key is pressed
05E3H-05E4H
CP 20H
Check to see if the key that was pressed in Register A is greater than a SPACE
05E5H-05E6H
Jump if the key that was pressed in Register A is greater than or equal to a SPACE
05E7H-05E8H
CP 0DH
Check to see if the key that was pressed in Register A is a CARRIAGE RETURN
05E9H-05EBH
Jump if the key that was pressed in Register A is a CARRIAGE RETURN
05ECH-05EDH
CP 1FH
Check to see if the key that was pressed in Register A is the CLEAR key
05EEH-05EFH
Jump if the key that was pressed in Register A is the CLEAR key
05F0H-05F1H
CP 01H
Check to see if the key that was pressed in Register A is the BREAK key
05F2H-05F3H
Jump if the key that was pressed in Register A is the BREAK key
05F4H-05F6H
LD DE,05E0H
Load register pair DE with the return address of 05E0H
05F7H
PUSH DE
Save the return address in register pair DE on the stack
05F8H-05F9H
CP 08H
Check to see if the key that was pressed in Register A is a backspace (which is 08) the cursor and erase character
05FAH-05FBH
Jump if the key was pressed in Register A is a backspace the cursor and erase character
05FCH-05FDH
CP 18H
Check to see if the key that was pressed in Register A is a backspace character
05FEH-05FFH
Jump if the key that was pressed in Register A is a backspace character
0600H-0601H
CP 09H
Check to see if the key that was pressed in Register A is a tab character
0602H-0603H
Jump if the key that was pressed in Register A is a tab character
0604H-0605H
CP 19H
Check to see if the key that was pressed in Register A is a turn on the 32 character per line mode character
0606H-0607H
Jump if the key that was pressed in Register A is a turn on the 32 character per line mode character
0608H-0609H
CP 0AH
Check to see if the key that was pressed in Register A is a line feed character of CHR$(10)
060AH
RET NZ
Return (to 05E0H) if the key that was pressed in Register A isn’t a line feed character
060BH
POP DE
Get the return address from the stack and put it in register pair DE (so that it isn’t 05E0H anymore)
060CH
LD (HL),A
We now know that the key pressed is a printable character so save the key that was pressed in Register A at the location of the input buffer pointer in register pair HL
060DH
LD A,B
Load Register A with the length of the buffer remaining in Register B
060EH
OR A
Check to see if there is any more of the input buffer remaining (and set status)
060FH-0610H
Jump to 05E0H if the end of the input buffer has been reached
0611H
LD A,(HL)
Now we know the end of the input buffer has not been reached, so load Register A with the value at the location of the input buffer pointer in register pair HL
0612H
INC HL
Increment the input buffer pointer in register pair HL
0613H-0615H
Display the character by calling the DISPLAY A CHARACTER routine at 0033H (which puts the character in Register A on the video screen)
0616H
DEC B
Decrement the number of bytes remaining in the input buffer area in Register B
0617H-0618H
Jump to 05E0H to get the next character
0619H-061BH
Call the CLEAR SCREEN routine at 01C9H (which clears the screen, changes to 64 characters, and homes the screen)
061CH
LD B,C
Load Register B with the length of the input buffer in register C (which resets the counter of characters transmitted)
061DH
POP HL
Get the starting address for the input buffer area from the stack and put it in register pair HL (which resets the buffer address)
061EH
PUSH HL
Save the starting address for the input buffer area in register pair HL on the stack
061FH-0621H
Jump to 05E0H (to get the next character, which is now the first character in the buffer)
0622H-0624H
Gosub to wait for the next key and back up the input buffer pointer in register pair HL if necessary
0625H
DEC HL
Backup to the previous character (the one before the CARRIAGE RETURN) by decrementing the input buffer pointer in register pair HL
0626H
LD A,(HL)
Load Register A with the character at the location of the input buffer pointer in register pair HL
0627H
INC HL
Increment the input buffer pointer in register pair HL to the net availabile position
0628H-0629H
CP 0AH
Check to see if the character in Register A is the line feed character of CHR$(10)
062AH
RET Z
Return if the character in Register A is a line feed character
062BH
LD A,B
Now we know that character wasn’t a line feed, so we need to test for a buffer full. This loads Register A with the number of bytes remaining in the input buffer area in Register B
062CH
CP C
Check to see if the number of characters remaining in the input buffer area in Register A is the same as the length of the input buffer area in register C
062DH-062EH
Jump to 0622H if there is room for more characters
062FH
RET
The buffer is full! Return

0630H – This subroutine assumes B is the number of characters received, and C is the size of the buffer.

0630H
LD A,B
Load Register A with the number of bytes remaining in the input buffer area in Register B
0631H
CP C
Compare the number of bytes remaining in the input buffer (held in Register A) against the size of the buffer (held in Register C) to see if the buffer is full
0632H
RET Z
Return if the input buffer area is full
0633H
DEC HL
Decrement the input buffer area pointer in register pair HL to backspace the previous character ..
0634H
LD A,(HL)
… and then get that character into Register A
0635H-0636H
CP 0AH
Check to see if the character in Register A is the line feed character of CHR$(10)
0637H
INC HL
Increment the input buffer area pointer in register pair HL
0638H
RET Z
Return if the character in Register A is a line feed character
0639H
DEC HL
Decrement the input buffer area pointer in register pair HL to backspace the previous character in the buffer ..
063AH-063BH
LD A,08H
Load Register A with a backspace of CHR$(08) and then ..
063CH-063EH
Effectuate the backspace by calling the DISPLAY A CHARACTER routine at 0033H (which puts the character in Register A on the video screen)
063FH
INC B
Increment the number of characters remaining in the input buffer area in Register B
0640H
RET
Return

0641H – This subroutine sends the position command.

0641H-0642H
LD A,17H
Load Register A with mask of 00010111 so as to turn on the 32 character per line mode character
0643H-0645H
Call the DISPLAY A CHARACTER routine at 0033H (which puts the character in Register A on the video screen). Since that is the 32 character per line mode, that’s what happens
0646H-0648H
Go get the cursor line position and return with it in Register A
0649H-064AH
AND 07H
Mask the cursor line position in Register A by ANDing it against 0000 0111
064BH
CPL
Inverse the value in Register A
064CH
INC A
Increment the value in Register A so that it is 1 <= A <= 8
064DH-064EH
ADD 08H
Clear the upper bits of the counter
064FH
LD E,A
Load register E with the number of spaces to be added in Register A
0650H
LD A,B
Load Register A with the number of bytes remaining in the input buffer area in Register B
0651H
OR A
Check to see if the buffer is full
0652H
RET Z
Return if the input buffer is full
0653H-0654H
LD A,20H
Load Register A with a space character
0655H
LD (HL),A
Save the space character in Register A at the location of the input buffer area pointer in register pair HL
0656H
INC HL
Increment the input buffer area pointer in register pair HL
0657H
PUSH DE
Save the value in register pair DE on the stack
0658H-065AH
Display the space by calling the DISPLAY A CHARACTER routine at 0033H (which puts the character in Register A on the video screen)
065BH
POP DE
Get the value from the stack and put it in register pair DE
065CH
DEC B
Since you just displayed one of the spaces, decrement the number of bytes remaining in the input buffer area in Register B ..
065DH
DEC E
… and decrement the number of spaces to be added in register E
065EH
RET Z
Return if the number of spaces has been added to the input buffer
065FH-0660H
Loop back to 0650H until all the spaces have been added to the input buffer

0661H – This subroutine is called when a BREAK key is hit.

0661H
SCF
Set the Carry flag. This is done because the routine is going to exit with the CARRY flag set as an indication that BREAK was hit.
0662H
PUSH AF
Save the value in register pair AF on the stack, which saves the CARRY flag
0663H-0664H
LD A,0DH
Load Register A with a carriage return character
0665H
LD (HL),A
Save the carriage return character in Register A at the location of the input buffer area pointer in register pair HL
0666H-0668H
Display the carriage return by calling the DISPLAY A CHARACTER routine at 0033H (which puts the character in Register A on the video screen). Since that is a CARRIAGE RETURN, that’s what happens
0669H-066AH
LD A,0FH
Load Register A with a turn off the cursor character
066BH-066DH
Turn off the cursor by calling the DISPLAY A CHARACTER routine at 0033H (which puts the character in Register A on the video screen)
066EH
LD A,C
Load Register A with the length of the input (=buffer size) in register C
066FH
SUB B
Subtract the number of bytes remaining in the input buffer area in Register B from the length of the input buffer area in Register A
0670H
LD B,A
Load Register B with the number of characters in the input buffer area in Register A
0671H
POP AF
Get the value from the stack and put it in register pair AF. This also sets the CARRY flag if BREAK and unsets it if CARRIAGE RETURN
0672H
POP HL
Get the starting address of the input buffer area from the stack and put it in register pair HL
0673H
RET
Return

0674H-06D1H – INITIALIZATION ROUTINE

0674H-0675H
OUT (0FFH),A
Send the zero in Register A out the video/cassette port. Earlier versions of the ROM looped back to this instruction instead of the next one, which pounded 0FFH!
0676H-0678H
LD HL,06D2H
Load register pair HL with the starting address of the video/keyboard/printer DCB’s
0679H-067BH
LD DE,4000H
Load register pair DE with the starting address of the communications region
067CH-067EH
LD BC,0036H
Load register pair BC with the length of the ROM area to be moved (which is 54 bytes)
067FH-0680H
LDIR
Move the 06D2H-0707H to the RAM scratch area of 4000H-4035H
0681H
DEC A
Decrement the value in Register A
0682H
DEC A
Decrement the value in Register A
0683H-0684H
Loop back to 0674H until the block move has occurred 128 times, jump to 0674H (which sends a click to the cassette port)
*0683H-0684H
Loop back to 0676H until the block move has occurred 128 times, jump to 0676H (which runs the routine AFTER the click, so no more click)
0685H-0686H
LD B,27H
Load Register B with the number of bytes of memory to be zeroed (which is 39)
0687H
LD (DE),A
Save the zero in Register A at the location of the memory pointer in register pair DE
0688H
INC DE
Increment the destination pointer in register pair DE
0689H-068AH
Loop back to 0687H until all of the memory locations between 4036H and 4062H have been zeroed
068BH-068DH
LD A,(3840H)
Load Register A with the location of keyboard memory for the BREAK key (which is 14400)
068EH-068FH
AND 04H
Check to see if the BREAK key is being pressed
0690H-0692H
Jump to 0075H if the BREAK key was pressed, and flow down if it wasn’t

This is the beginning of the routine which boots a diskette.

0693H-0695H
LD SP,407DH
Set the stack pointer to 407DH
0696H-0698H
LD A,(37ECH)
Load Register A with the status of the disk controller (which is stored in 37ECH)
0699H
INC A
Increment the value in Register A so that we can ..
069AH-069BH
CP 02H
… check to see if the disk controller is present
069CH-069EH
Jump to the Level II Initialization Routine at 0075H if the disk controller isn’t present
069FH-06A0H
LD A,01H
So now we know there is a disk controller, so lets load Register A with the unit select mask for Drive :0
06A1H-06A3H
LD (37E1H),A
Select Drive :0 (by loading 01H into 37E1H)
06A4H-06A6H
LD HL,37ECH
Load register pair HL with the address of the disk command/status register of 37ECH
06A7H-06A9H
LD DE,37EFH
Load register pair DE with the address of the disk data register of 37EFH
06AAH-06ABH
LD (HL),03H
Load the disk command/status register (37ECH) with command 03H (RESTORE and POSITION TO TRACK 0). More specifically, this sends 0000 0011 to the register, which is broken down as follows (left to right): Restore (0000), Do NOT load head (0), Verify Off (0), 20 ms step (11)
06ACH-06AEH
LD BC,0000H
Load register pair BC with the delay count
06AFH-06B1H
Call the delay routine at 0060H (which will delay BC times 14.65; about 3 seconds)
06B2H-06B3H
BIT 0,(HL)
Check to see if the diskette controller is busy by testing Bit 0 of 37ECH (Floppy Disk Controller Status). Bit 0 is the BUSY status bit. Per WD, commands should only be loaded into the command register when the Busy Status but is off.
06B4H-06B5H
Loop back to that test in 06B2H until the disk is no longer busy
06B6H
XOR A
Zero Register A

This routine loads Drive 0, Track 0, Sector 0 into 4200H-4455H, and then jumps to 4200H.

06B7H-06B9H
LD (37EEH),A
Save the value in Register A in the disk sector register (at 37EEH)
06BAH-06BCH
LD BC,4200H
Load register pair BC with the address in memory to place the sector read (which is 4200H)
06BDH-06BEH
LD A,8CH
Load Register A with the command to read the sector. More specifically, send 10001100, which is broken down (from left to right) as Read Sector (100xxx00), Single Record (0), IBM Format (1), Enable HLD, HLT, and 10 msec delay.
06BFH
LD (HL),A
Put the command in Register A (read the sector) in the disk command register of 37ECH. This then reads Drive 0 Track 0 Sector 0 into 4200H-4455H
06C0H-06C1H
BIT 1,(HL)
Check the disk command/status register of 37ECH to see if there is data available
06C2H-06C3H
Loop back to the prior instruction until there is data available
06C4H
LD A,(DE)
So now we know there is data available, so we load Register A with the byte read from the disk (i.e., the data in disk data register of 37EFH)
06C5H
LD (BC),A
Save the value in Register A at the location of the memory pointer in register pair BC (4200H-4455H)
06C6H
INC C
Increment the LSB of the memory pointer in register C
06C7H-06C8H
Loop back to 06C0H until the whole 256 bytes of the sector has been read into 4200H-4455H
06C9H-06CBH
Now that the entire first sector has been read into 4200H-4455H, jump there!

06CCH-06CEH – Alternative re-entry point into BASIC.

  • A JP to here is often better than a jump to lA19H as the latter sometimes does strange things to any resident BASIC program.
06CCH-06CEH
LD BC,1A18H
Load register pair BC with the starting address of the Level II BASIC READY routine (which is kept at 1A18H)
06CFH-06D1H
Jump to 19AEH to initialize BASIC’s variables and pointers

06D2H-0707H – ROM STORAGE LOCATION FOR DATA TO BE MOVED TO RAM BY THE INITIALIZATION PROCESS.

06D2H
This will be 4000H – it is a jump to the RST 08H routine (COMPARE SYMBOL routine). DOS will overwrite this value.
06D5H
This will be 4003H – it is a jump to RST 10H (get the next character). DOS will overwrite this value.
06D8H
This will be 4006H – it is a jump to RST 18H (compare DE and HL). DOS will overwrite this value.
06DBH
This will be 4009H – it is a jump to RST 20H (tests for data type). DOS will overwrite this value.
06DEH
RET
This will be 400CH – is a RETurn from RST 28H (which is a jump to 4BA2H for DOS)
06DFH
NOP
06E0H
NOP
06E1H
RET
This will be 400FH – it is a RETurn from RST 30H (which is a jump to 44B4H for DOS)
06E2H
NOP
06E3H
NOP
This will be 4012H – RST 38H vector DI/RET (JP 4518H for DOS)
06E4H
EI
This is the interrfupt entry point vector
06E5H
RET
06E6H
NOP
06E7H
LD BC,03E3H
This will be 4015H – The keyboard DCB
06EAH
NOP
06EBH
NOP
06ECH
NOP
06EDH
LD C,E
06EEH
LD C,C
This will be 401DH – The video DCB
06EFH
RLCA
06F0H
LD E,B
06F1H
INC B
06F2H
NOP
06F3H
INC A
06F4H
NOP
06F5H
LD B,H
06F6H
LD C,A
This will be 4025H – The line printer DCB
06F7H
LD B,8DH
06F9H
DEC B
06FAH
LD B,E
06FBH
NOP
06FCH
NOP
06FDH
LD D,B
06FEH
LD D,D
06FFH
JP 5000H
This will be 402DH, and SYS 0 will change this to JP 4400H
0702H
RST 00H
This will be 4030H, and SYS 0 will change this to LD A,A3H
0703H
NOP
0704H
NOP
This will be 4032H, and SYS 0 will change this to RST 28H
0705H
LD A,00H
This will be 4033H, and SYS 0 will change this to 44BBH
0707H
RET

070BH-070FH – SINGLE PRECISION ADDITION, REG 1 = (HL) + REG 1

  • Single-precision addition (REG 1=(HL)+ACC) involving a buffer pointed to by the HL register pair and REG 1 (see arithmetic section in Part 2 of this manual for information on the ACC). This part of the program loads the BCDE registers with the value from the buffer, then passes control to 716H.
0708H-070AH
LD HL,1380H
Load register pair HL with the starting address of a single precision value stored in ROM at 1380H
070BH-070DH
Call 09C2H (which loads a SINGLE PRECISION value pointed to by register pair HL into register pairs BC and DE)
070EH-070FH
Jump to the SINGLE PRECISION ADD routine at 0716H (which adds the single precision value in (BC/DE) to the single precision value in REG 1. The sum is left in REG 1)

0710H-0712H – SINGLE PRECISION SUBTRACTION, REG 1 = (HL) – REG 1

  • Single-precision subtraction (REG 1=(HL)-REG 1). This loads the BCDE registers with the value from (HL), then passes control to 0713H.
0710H-0712H
Call 09C2H (which loads a SINGLE PRECISION value pointed to by register pair HL into register pairs BC and DE)

0713H-0715H – SINGLE PRECISION SUBTRACTION, REG 1 = BCDE – REG 1
“SUBSP”

  • Single-precision subtraction (REG 1=BCDE-REG 1). The routine actually inverts REG 1 and adds it to the contents of the BCDE registers which, in effect, is a subtraction. The result will be stored in the arithmetic work area (REG 1).
  • Note: If you wanted to subtract two single precision numbers, store the minuend in the BCDE registers and store the subtrahend in 4121H-4124H and then CALL 0713H. The result (in single precision format) is in 4121H-4124H in approximately 670 microseconds.

.

0713H-0715H
“SSUB”
Go reverse the sign of the single precision value in register pairs BC and DE

0716H-0752H – SINGLE PRECISION ADDITION, REG 1 = BCDE + REG 1
“ADDSP”

  • Single-precision addition (REG 1=BCDE+ACC). This routine adds two single-precision values and stores the result in REG 1 area.
  • Note: If you wanted to add 2 single precision numbers via a ROM call, store one input into BCDE (with the exponent in B and the LSB in E) and the other into 4121H-4124H, and then call 0716H. The single precision result will be in 4121H-4124H approximately 1.3 milliseconds later.
0716H
“SADD”
LD A,B
Load Register A with the exponent of the single precision value in Register B
0717H
OR A
Check to see if the single precision value in register pairs BC and DE is equal to zero
0718H
RET Z
Return if the single precision value in register pairs BC and DE is equal to zero
0719H-071BH
LD A,(4124H)
Load Register A with the exponent of the single precision value in REG 1 (which is stored in 4124H)
071CH
OR A
Check to see if the single precision value in REG 1 is equal to zero
071DH-071FH
Jump to 09B4H (which moves the SINGLE PRECISION value in DC/DE into REG 1) if the single precision value in REG 1 is equal to zero
0720H
SUB B
Subtract the value of the exponent for the single precision value in Register B from the value of the exponent for the single precision value in REG 1 in Register A.
0721H-0722H
Jump if the single precision value in register pairs BC and DE is smaller than the single precision value in REG 1
0723H
CPL
Adjust the difference in the exponents in Register A so that it is positive
0724H
INC A
Increment the difference in the exponents in Register A so that it will be the correct positive number
0725H
EX DE,HL
Load register pair HL with the 16-bit value in register pair DE
0726H-0728H
Call 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order)
0729H
EX DE,HL
Load register pair DE with the 16-bit value in register pair HL
072AH-072CH
Call 09B4H which moves the SINGLE PRECISION value in DC/DE into REG 1
072DH
POP BC
Get the 16-bit value from the stack and put it in register pair BC
072EH
POP DE
Get the 16-bit value from the stack and put it in register pair DE
072FH-0730H
CP 19H
Check to see if the difference in the exponents in Register A is greater than 24 (because if it is, the numbre cannot be added because of the difference in magnitude)
0731H
RET NC
Return if the difference in the exponents is too great
0732H
PUSH AF
Save the difference in the exponents in Register A on the stack
0733H-0735H
Set the sign bits for the single precision values and return with the equality of the sign bits in Register A
0736H
LD H,A
Load register H with the equality of the sign bits in Register A
0737H
POP AF
Get the difference of the exponents from the stack and put it in Register A
0738H-073AH
Go shift the single precision value in register pairs BC and DE until it lines up with the single precision value in REG 1
073BH
OR H
Check to see if the sign bits are equal
073CH-073EH
LD HL,4121H
Load register pair HL with the starting address of REG 1
073FH-0741H
Jump if the signs aren’t equal
0742H-0744H
Go add the single precision value in BCDE to the single precision value in REG 1
0745H-0747H
Jump if the exponent remains unchanged
0748H
INC HL
Increment the memory pointer in register pair HL, so that it points to the exponent in REG 1
0749H
INC (HL)
Increment the exponent in REG 1 at the location of the memory pointer in register pair HL
074AH-074CH
If the exponent in REG 1 is too large, go to 07B2H to output an OV ERROR message
074DH-074EH
LD L,01H
Load register L with the number of bits to shift the single precision result in register pairs BC and DE
074FH-0751H
Go shift the single precision result in register pairs BC and DE
0752H-0753H
Jump to 0796H

0754H-077CH – SINGLE PRECISION MATH ROUTINE

0754H
XOR A
Zero Register A
0755H
SUB B
Subtract the 8-bit value in Register B from the value in Register A
0756H
LD B,A
Load Register B with the result in Register A
0757H
LD A,(HL)
Load Register A with the value at the memory pointer in register pair HL
0758H
SBC A,E
Subtract the value in register E from the value in Register A
0759H
LD E,A
Load register E with the result in Register A
075AH
INC HL
Increment the memory pointer in register pair HL
075BH
LD A,(HL)
Load Register A with the value at the location of the memory pointer in register pair HL
075CH
SBC A,D
Subtract the value in register D from the value in Register A
075DH
LD D,A
Load register D with the result in Register A
075EH
INC HL
Increment the memory pointer in register pair HL
075FH
LD A,(HL)
Load Register A with the value at the location of the memory pointer in register pair HL
0760H
SBC A,C
Subtract the value in register C from the value in Register A
0761H
LD C,A
Load register C with the result in Register A
0762H-0764H
If the Carry flag is set, go convert the single precision value to a positive number
0765H
LD L,B
Load register L with the exponent of the original value in register pairs BC and DE
0766H
LD H,E
Load register H with the LSB of the single precision value in register E
0767H
XOR A
Zero Register A
0768H
LD B,A
Load Register B with the new exponent in Register A
0769H
LD A,C
Load Register A with the MSB of the single precision value in register C
076AH
OR A
Check to see if the value in Register A is equal to zero
076BH-076CH
Jump if the MSB of the single precision value is nonzero
076DH
LD C,D
Shift the NMSB into the MSB by loading register C with the value in register D
076EH
LD D,H
Shift the LSB into the NMSB by loading register D with the value in register H
076FH
LD H,L
Load register H with the value in register L
0770H
LD L,A
Load register L with the value in Register A
0771H
LD A,B
Load Register A with the new exponent counter in Register B
0772H-0773H
SUB 08H
Subtract the number of bits just shifted from the new exponent counter in Register A
0774H-0775H
CP E0H
Check to see if three bytes have been shifted
0776H-0777H
Loop until shift is completed
0778H
“RSETSA”
XOR A
Zero Register A
0779H-077BH
LD (4124H),A
Save the value in Register A as the exponent of the single precision result in REG 1 (which is 16676)
077CH
RET
Return with a single precision value of zero in REG 1

077DH-07A7H – SINGLE PRECISION MATH ROUTINE

077DH
DEC B
Decrement the new exponent counter in Register B
077EH
ADD HL,HL
Shift the 16-bit value in register pair HL left one bit
077FH
LD A,D
Load Register A with the NMSB in register D
0780H
RLA
Shift the NMSB in Register A left one bit and shift a bit from register pair HL if necessary
0781H
LD D,A
Save the adjusted NMSB in Register A into register D
0782H
LD A,C
Load Register A with the MSB in register C
0783H
ADC A,A
Shift the MSB in Register A left one bit and shift a bit from register D if necessary
0784H
LD C,A
Load register C with the adjusted value in Register A
0785H-0787H
Loop until the most significant bit of the single precision value is equal to one
0788H
LD A,B
Load Register A with the new exponent counter in Register B
0789H
LD E,H
Load register E with the LSB of the single precision value in register H
078AH
LD B,L
Load Register B with the value in register L
078BH
OR A
Check to see if there were any bits shifted
078CH-078DH
Jump if there weren’t any bits shifted
078EH-0790H
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
0791H
ADD A,(HL)
Add the value of the original exponent at the location of the memory pointer in register pair HL to the number of bits shifted in Register A
0792H
LD (HL),A
Save the new exponent in Register A at the location of the memory pointer in register pair HL
0793H-0794H
Jump if exponent is too small. This jump is to code which just zeroes out A, puts it into (4124H), and RETurns
0795H
RET Z
Return if exponent is equal to zero
0796H
LD A,B
Load Register A with the LSB of the single precision value in Register B
0797H-0799H
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
079AH
OR A
Check to see if the most significant bit of the value in Register A is set
079BH-079DH
Go check for overflow if the most significant bit in the value in Register A is set
079EH
LD B,(HL)
Load Register B with the exponent at the location of the memory pointer in register pair HL
079FH
INC HL
Increment the memory pointer in register pair HL
07A0H
LD A,(HL)
Load Register A with the value of the sign at the location of the memory pointer in register pair HL
07A1H-07A2H
AND 80H
Mask the sign bit in Register A (1000 0000)
07A3H
XOR C
Set the sign bit in Register A
07A4H
LD C,A
Load register C with the adjusted MSB of the single precision value in Register A
07A5H-07A7H
Jump to 09B4H (which moves the SINGLE PRECISION value in DC/DE into REG 1)

07A8H-07B6H – SINGLE PRECISION MATH ROUTINE

07A8H
INC E
Increment the LSB of the single precision value in register E
07A9H
RET NZ
Return if the adjusted LSB of the single precision value in register E is nonzero
07AAH
INC D
Increment the NMSB of the single precision value in register D
O7ABH
RET NZ
Return if the adjusted NMSB of the single precision value in register D is nonzero
07ACH
INC C
Increment the MSB of the single precision value in register C
07ADH
RET NZ
Return if the adjusted MSB of the single precision value in register C is nonzero
07AEH-07AFH
LD C,80H
Adjust the MSB of the single precision value in register C
07B0H
INC (HL)
Increment the exponent of the single precision value at the location of the memory pointer in register pair HL
07B1H
RET NZ
Return if the adjusted exponent of the single precision value at the location of the memory pointer in register pair HL is nonzero
07B2H-07B3H
LD E,0AH
Load register E with an OV ERROR code.

This is the OV ERROR entry point
07B4H-07B6H
Go to the Level II BASIC error routine and display an OV ERROR message if the value has overflowed

07B7H-07C2H SINGLE PRECISION MATH ROUTINE

07B7H
LD A,(HL)
Load Register A with the LSB of the single precision value at the location of the memory pointer in register pair HL
07B8H
ADD A,E
Add the LSB of the single precision value in register E to the LSB of the single precision value in Register A
07B9H
LD E,A
Load register E with the result in Register A
07BAH
INC HL
Increment the memory pointer in register pair HL
07BBH
LD A,(HL)
Load Register A with the NMSB of the single precision value in REG 1 at the location of the memory pointer in register pair HL
07BCH
ADC A,D
Add the NMSB of the single precision value in register D to the NMSB of the single precision value in Register A
07BDH
LD D,A
Load register D with the result in Register A
07BEH
INC HL
Increment the memory pointer in register pair HL
07BFH
LD A,(HL)
Load Register A with the MSB of the single precision value in REG 1 at the location of the memory pointer in register pair HL
07C0H
ADC A,C
Add the MSB of the single precision value in register C to the MSB of the single precision value in Register A
07C1H
LD C,A
Load register C with the result in Register A
07C2H
RET
Return

07C3H-07D6H – SINGLE PRECISION MATH ROUTINE – Convert to a single precision number to positive.

07C3H-07C5H
LD HL,4125H
Load register pair HL with the address of the sign flag storage location.
Note: 4125H-4126H is used by floating point routines
07C6H
LD A,(HL)
Load Register A with the value of the sign flag at the location of the memory pointer in register pair HL
07C7H
CPL
Complement the sign flag in Register A
07C8H
LD (HL),A
Save the adjusted sign flag in Register A at the location of the memory pointer in register pair HL
07C9H
XOR A
Zero Register A
07CAH
LD L,A
Load register L with the value in Register A
07CBH
SUB B
Figure the negative value for Register B by subtracting the current value in Register B from the value in Register A
07CCH
LD B,A
Save the adjusted value in Register A in Register B
07CDH
LD A,L
Load Register A with zero
07CEH
SBC A,E
Figure the negative LSB of the single precision value in register E by subtracting the current LSB of the single precision value in register E from the value in Register A
07CFH
LD E,A
Load register E with the adjusted LSB of the single precision value in Register A
07D0H
LD A,L
Load Register A with zero
07D1H
SBC A,D
Figure the negative NMSB of the single precision value in register D by subtracting the current NMSB of the single precision value in register D from the value in Register A
07D2H
LD D,A
Load register D with the adjusted NMSB of the single precision value in Register A
07D3H
LD A,L
Load Register A with zero
07D4H
SBC A,C
Figure the negative MSB of the single precision value in register C by subtracting the current MSB of the single precision value in register C from the value in Register A
07D5H
LD C,A
Load register C with the adjusted MSB of the single precision value in Register A
07D6H
RET
Return

07D7H-07F7H – SINGLE PRECISION MATH ROUTINE

07D7H-07D8H
LD B,00H
Load Register B with zero
07D9H-07DAH
SUB 08H
Check to see if the shift counter in Register A still indicates at least 8 bits have to be shifted
07DBH-07DCH
Jump if less than 8 bits are left to be shifted
07DDH
LD B,E
Load Register B with the LSB of the single precision value in register E
07DEH
LD E,D
Load register E with the NMSB of the single precision value in register D
07DFH
LD D,C
Load register D with the MSB of the single precision value in register C
07E0H-07E1H
LD C,00H
Load register C with zero
07E2H-07E3H
Loop until there is less than 8 bits left to be shifted
07E4H-07E5H
ADD 09H
Adjust the shift counter in Register A to its correct value
07E6H
LD L,A
Load register L with the shift counter in Register A
07E7H
XOR A
Zero Register A
07E8H
DEC L
Decrement the shift counter in register L
07E9H
RET Z
Return if there are no more bits to be shifted
07EAH
LD A,C
Load Register A with the MSB of the single precision value in register C
07EBH
RRA
Shift the MSB of the single precision value in Register A one place to the right
07ECH
LD C,A
Load register C with the adjusted MSB of the single precision value in Register A
07EDH
LD A,D
Load Register A with the NMSB of the single precision value in register D
07EEH
RRA
Shift the NMSB of the single precision value in Register A one place to the right and pick up the value of the Carry flag
07EFH
LD D,A
Load register D with the adjusted NMSB of the single precision value in Register A
07F0H
LD A,E
Load Register A with the LSB of the single precision value in register E
07F1H
RRA
Shift the LSB of the single precision value in Register A one place to the right and pick up the value of the Carry flag
07F2H
LD E,A
Load register E with the adjusted LSB of the single precision value in Register A
07F3H
LD A,B
Load Register A with the value in Register B
07F4H
RRA
Shift the value in Register A one place to the right and pick up the value of the Carry flag
07F5H
LD B,A
Load Register B with the adjusted value in Register A
07F6H-07F7H
Loop until all of the bits have been shifted

07F8H-07FBH – SINGLE PRECISION CONSTANT STORAGE LOCATION

07F8H-07FBH
00 00 00 81
A single precision constant equal to 1.0 is stored here

07FCH-0808H – SINGLE PRECISION CONSTANTS STORAGE LOCATION2

07FCH
03
The number of single precision constants which follows is stored here
07FDH-0800H
AA 56 19 80
A single precision constant equal to .598978 is stored here
0801H-0804H
F1 22 76 80
A single precision constant equal to .961471 is stored here
0805H-0808H
45 AA 38 82
A single precision constant equal to 2.88539 is stored here

0809H-0846H – LEVEL II BASIC LOG ROUTINE – LOG

  • The LOG(n) routine, (REG 1=LOG (REG 1)). This routine finds the LOGarithm of the value in REG 1 area.
    A call to 0809H computes the natural log (base E) of the single precision value in REG 1. The result is returned as a single precision value in REG 1.
  • NOTE: To use a ROM call to find LOG(X), where X is a positive single precision variable, store the value of X in 4121H-4124H and then CALL 0809H. The result (in single precision format) is in 4121H-4124Hin approximately 19 milliseconds. NOTE: A fatal error occurs if the value of the input variable is zero or negative.
0809H-080BH
“LOG”
Go check the sign of the single precision value in REG 1
080CH
OR A
Check to see if the single precision value in REG 1 is negative or positive
080DH-080FH
Go the Level II BASIC error routine and display a FC ERROR message if the current single precision value in REG 1 is negative
0810H-0812H
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
0813H
LD A,(HL)
Load Register A with the exponent of the single precision value in REG 1 at the location of the memory pointer in register pair HL
0814H-0816H
LD BC,8035H
Load Register BC with the exponent and the MSB of a single precision constant (which is 32821)
0817H-0819H
LD DE,04F3H
Load register DE with the NMSB and the LSB of a single precision constant (which is 1267). Register pairs BC and DE are now equal to the single precision constant of .707107
081AH
SUB B
Subtract the exponent in Register B from the exponent of the x-value in Register A
081BH
PUSH AF
Save the difference between the two exponents in Register A on the stack
081CH
LD (HL),B
Save the exponent in Register B as the exponent of the x-value in REG 1 at the location of the memory pointer in register pair HL
081DH
PUSH DE
Save the NMSB and the LSB of the single precision value in register pair DE on the stack
081EH
PUSH BC
Save the exponent and the MSB of the single value in register pair BC on the stack
081FH-0831H
Go add the x-value to the single precision constant in register pairs BC and DE and return with the result in REG 1, by calling the SINGLE PRECISION ADD routine at 0716H (which adds the single precision value in (BC/DE) to the single precision value in REG 1. The sum is left in REG 1)
0822H
POP BC
Get the exponent and the MSB of the single precision value from the stack and put it in register pair BC
0823H
POP DE
Get the NMSB and the LSB of the single precision value from the stack and put it in register pair DE
0824H
INC B
Multiply the single precision value in register pairs BC and DE by two by bumping the exponent in Register B
0825H-0827H
Go divide the single precision value in register pairs BC and DE by the x-value in REG 1 and return with the result in REG 1
0828H-082AH
LD HL,07F8H
Load register pair HL with the starting address of a single precision constant (which is at 2040)
082BH-082DH
Go subtract the x-value in REG 1 from the single precision constant of 1. 0 at the location of the memory pointer in register pair HL and return with the result in REG 1
082EH-0830H
LD HL,07FCH
Load register pair HL with the starting address of a storage location for single precision constants to be used for a series of computations (which is at 2044)
0831H-0833H
Go do a series of computations and return with the result in REG 1
0834H-0836H
LD BC,8080H
Load Register BC with the exponent and the MSB of a single precision constant
0837H-0839H
LD DE,0000H
Load register pair DE with the NMSB and the LSB of a single precision. Register pairs BC and DE are now equal to a single precision of -0.5
083AH-083CH
Go add the x-value in REG 1 to the single precision constant in register pairs BC and DE and return with the result in REG 1, by calling the SINGLE PRECISION ADD routine at 0716H (which adds the single precision value in (BC/DE) to the single precision value in REG 1. The sum is left in REG 1)
083DH
POP AF
Get the difference between the two original exponents from the stack and put it in Register A
083EH-0840H
Go convert the value in Register A to a single precision number and add it to the x-value in REG 1. Return with the result in REG 1
0841H-0843H
LD BC,8031H
Load register pair BC with the exponent and the MSB of a single precision constant
0844H-0846H
LD DE,7218H
Load register pair DE with the NMSB and the LSB of a single precision constant. Register pairs BC and DE are now equal to a single precision value of 0.693147

0847H-0891H – SINGLE PRECISION MULTIPLICATION, REG 1 = BCDE * REG 1 – “MLTSP”

  • Single-precision multiplication (REG 1=BCDE*ACC).
    Multiplies the current value in WRAl by the value in (BC/DE). the product is left in WRAl.
  • Note: If you wanted to multiply two single precision numbers store one operand in the BCDE registers, the other in 4121H-4124H CALL 0847H. The result (in single precision format) is in 4121H-4124H in approximately 2.2 milliseconds.
0847H-0849H
“SMUL”
Go check to see if the single precision value in REG 1 is equal to zero
084AH
RET Z
Return if the single precision value in REG 1 is equal to zero
084BH-084CH
LD L,00H
Load register L with a bit mask
084DH-084FH
Go check for possible overflow and the single precision value in register pairs BC and DE equal to zero
0850H
LD A,C
Load Register A with the single precision value’s MSB in register C
0851H-0853H
LD (414FH),A
Save the MSB of the single precision value in Register A at memory location 414FH
0854H
EX DE,HL
Load register pair HL with the NMSB and the LSB of the single precision value in register pair DE
0855H-0857H
LD (4150H),HL
Save the NMSB and the LSB of the single precision value in register pair HL at memory locations 4150H and 4151H
0858H-085AH
LD BC,0000H
Load register pair BC with zero
085BH
LD D,B
Load register D with the value in Register B
085CH
LD E,B
Load register E with the value in Register B
085DH-085FH
LD HL,0765H
Load register pair HL with the return address
0860H
PUSH HL
Save the return address in register pair HL on the stack
0861H-0863H
LD HL,0869H
Load register pair HL with the return address
0864H
PUSH HL
Save the return address in register pair HL on the stack
0865H
PUSH HL
Save the return address in register pair HL on the stack
0866H-0868H
LD HL,4121H
Load register pair HL with the starting address of the single precision value in REG 1
0869H
LD A,(HL)
Load Register A with the LSB of the single precision value in REG 1 at the location of the memory pointer in register pair HL
085AH
INC HL
Increment the memory pointer in register pair HL
085BH
OR A
Check to see if the LSB of the single precision value in REG 1 in Register A is equal to zero
086CH-086DH
Jump if the LSB of the single precision value in REG 1 is equal to zero
086EH
PUSH HL
Save the memory pointer in register HL on the stack
086FH-0870H
LD L,08H
Load register L with the bit shift counter
0871H
RRA
Shift the LSB of the single precision value in REG 1 in Register A one place to the right
0872H
LD H,A
Load register H with the adjusted LSB in Register A
0873H
LD A,C
Load Register A with the MSB of the single precision value in register C
0874H-0875H
Jump forward to 0881H if bit 0 in the LSB just shifted wasn’t set
0876H
PUSH HL
Save the value in register pair HL on the stack
0877H-0879H
LD HL,(4150H)
Load register pair HL with the NMSB and the LSB of the original value in register pairs BC and DE
087AH
ADD HL,DE
Add the NMSB and the LSB of the total figured so far in register pair DE to the NMSB and the LSB of the original value in register pair HL
087BH
EX DE,HL
Load register pair DE with the adjusted total in register pair HL
087CH
POP HL
Get the value from the stack and put it in register pair HL
087DH-087FH
LD A,(414FH)
Load Register A with the MSB of the original value in register pairs BC and DE
0880H
ADC A,C
Add the MSB of the original value in Register A to the MSB of the total figured so far in register C
0881H
RRA
Shift the adjusted MSB of the total in Register A one place to the right
0882H
LD C,A
Load register C with the adjusted MSB of the total in Register A
0883H
LD A,D
Load Register A with the NMSB of the total in register D
0884H
RRA
Shift the NMSB of the total in Register A one place to the right
0885H
LD D,A
Load register D with the adjusted NMSB of the total in Register A
0886H
LD A,E
Load Register A with the LSB of the total in register E
0887H
RRA
Shift the LSB of the total in Register A one place to the right
0888H
LD E,A
Load register E with the adjusted LSB of the total in Register A
0889H
LD A,B
Load Register A with the value in Register B
088AH
RRA
Shift the value in Register A one place to the right
088BH
LD B,A
Load Register B with the adjusted value in Register A
088CH
DEC L
Decrement the bit counter in register L
088DH
LD A,H
Load Register A with the LSB of the current value in register H
088EH-088FH
Loop until 8 bits have been shifted
0890H
POP HL
Get the memory pointer from the stack and put it in register pair HL
0891H
RET
Return

0892H-0896H – SINGLE PRECISION MATH ROUTINE
This is accomplished by a circular shift of BC/DE one byte – B is lost, C is replaced by A.

0892H
LD B,E
Load Register B with the LSB of the single precision value in register E
0893H
LD E,D
Load register E with the NMSB of the single precision value in register D
0894H
LD D,C
Load register D with the MSB of the single precision value in register C
0895H
LD C,A
Load register C with the value in Register A
0896H
RET
Return

0897H-08AlH – SINGLE PRECISION MATH ROUTINE

0897H-0899H
Call 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order)
089AH-089CH
LD HL,0DD8H
Load register pair HL with the starting address of a single precision constant equal to 10
089DH-089FH
Call 09B1H (which moves a SINGLE PRECISION number pointed to by HL to REG 1)
08A0H
POP BC
Get the exponent and the MSB of the single precision value on the stack and put it in register pair BC
08A1H
POP DE
Get the NMSB and the LSB of the single precision value from the stack and put it in register pair DE

08A2H-0903H – SINGLE PRECISION DIVISION, REG 1 = BCDE / REG 1

  • “DIVSP” – Single-precision division (REG 1=BCDE/REG 1). If REG 1=0 a ” /0 ERROR ” will result.
    This routine will divide the SINGLE PRECISION value in register pairs BC and DE by the single precision value in REG 1. The result is returned in REG 1.
  • To use a ROM call to divide two single precision numbers, store the dividend in registers BCDE, and the divisor in 4121H-4124H and then CALL 08A2H. The result (in single precision format) is in 4121H-4124H and then pproximately 4.8 milliseconds. Overflow or /0 will error out and return to Level II.
08A2H-08A4H
“SDIV”
Go check to see if the single precision value in REG 1 is equal to zero
08A5H-08A7H
Go to the Level II BASIC error routine and display an /0 ERROR message if the single precision value in REG 1 is equal to zero
08A8H-08A9H
LD L,FFH
Load register L with a bit mask
08AAH-08ACH
Go adjust the exponent in REG 1 for division
08ADH
INC (HL)
Increment the value of the exponent for the single precision value in REG 1 at the location of the memory pointer in register pair HL
08AEH
INC (HL)
Increment the value of the exponent for the single precision value in REG 1 at the location of the memory pointer in register pair HL
08AFH
DEC HL
Decrement the value of the memory pointer in register pair HL
08B0H
LD A,(HL)
Load Register A with the MSB of the single precision value in REG 1 at the location of the memory pointer in register pair HL
08B1H-08B3H
LD (4089H),A
Save the MSB of the single precision value in REG 1 in Register A at memory location 4089H
08B4H
DEC HL
Decrement the value of the memory pointer in register pair HL
08B5H
LD A,(HL)
Load Register A with the NMSB of the single precision value in REG 1 at the location of the memory pointer in register pair HL
08B6H-08B8H
LD (4085H),A
Save the NMSB of the single precision value in REG 1 in Register A at memory location 4085H
08B9H
DEC HL
Decrement the value of the memory pointer in register pair HL
08BAH
LD A,(HL)
Load Register A with the LSB of the single precision value in REG 1 at the location of the memory pointer in register pair HL
08BBH-08BDH
LD (4081H),A
Save the LSB of the single precision value in REG 1 in Register A at memory location 4081H
08BEH
LD B,C
Load Register B with the MSB of the single precision value in register C
08BFH
EX DE,HL
Load register pair HL with the NMSB and the LSB of the single precision value in register pair DE
08C0H
XOR A
Zero Register A
08C1H
LD C,A
Zero the MSB of the total by loading register C with the value in Register A
08C2H
LD D,A
Zero the NMSB of the total by loading register D with the value in Register A
08C3H
LD E,A
Zero the LSB of the total by loading register E with the value in Register A
08C4H-08C6H
LD (408CH),A
Zero memory location 408CH
08C7H
PUSH HL
Save the NMSB and LSB of the dividend in register pair HL on the stack
08C8H
PUSH BC
Save the MSB of the dividend in Register B on the stack
08C9H
LD A,L
Load Register A with the LSB of the dividend in register L
08CAH-08CCH
Go to the Level II BASIC division routine.
Note: 4080H-408DH is a division support routine
08CDH-08CEH
SBC 00H
Adjust the flags
08CFH
CCF
Invert the Carry flag
08D0H-08D1H
Jump down to 08D9H (which is a Z-80 trick) if not done
08D2H-08D4H
LD (408CH),A
Save the value in Register A at memory location 408CH
08D5H
POP AF
Get the value from the stack and put it in register pair AF
08D6H
POP AF
Get the value from the stack and put it in register pair AF
08D7H
SCF
Set the Carry flag
08D8H
D2
Z-80 Trick – See the note at 0134H for an explanation
08D9H
POP BC
Get the value from the stack and put it in register pair BC
08DAH
POP HL
Get the value from the stack and put it in register pair HL
08DBH
LD A,C
Load Register A with the MSB of the total in register C
08DCH
INC A
Increment the MSB of the total in Register A
08DDH
DEC A
Decrement the MSB of the total in Register A
08DEH
RRA
Shift the MSB of the total in Register A one place to the right
08DFH-08E1H
Jump back to 0797H if done
08E2H
RLA
Reset the Carry flag
08E3H
LD A,E
Load Register A with the LSB of the total in register E
08E4H
RLA
Multiply the LSB of the total in Register A by two
08E5H
LD E,A
Load register E with the adjusted LSB of the total in Register A
08E6H
LD A,D
Load Register A with the NMSB of the total in register D
08E7H
RLA
Multiply the NMSB of the total in Register A by two
08E8H
LD D,A
Load register D with the adjusted NMSB of the total in Register A
08E9H
LD A,C
Load Register A with the MSB of the total in register C
08EAH
RLA
Multiply the MSB of the total in Register A by two
08EBH
LD C,A
Load register C with the adjusted MSB of the total in Register A
08ECH
ADD HL,HL
Multiply the NMSB and the LSB of the dividend in register pair HL by two
08EDH
LD A,B
Load Register A with the MSB of the dividend in Register B
08EEH
RLA
Multiply the MSB of the dividend in Register A by two
08EFH
LD B,A
Load Register B with the adjusted MSB of the dividend in Register A
08F0H-08F2H
LD A,(408CH)
Load Register A with the value at memory location 408CH
08F3H
RLA
Multiply the value in Register A by two
08F4H-08F6H
LD (408CH),A
Save the adjusted value in Register A at memory location 408CH
08F7H
LD A,C
Load Register A with the MSB of the total in register C
08F8H
OR D
Combine the NMSB of the total in register D with the value in Register A
08F9H
OR E
Combine the LSB of the total in register E with the value in Register A
08FAH-08FBH
Jump back to 08C7H if the total isn’t equal to zero
08FCH
PUSH HL
Save the NMSB and the LSB of the dividend in register pair HL on the stack
08FDH-08FFH
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
0900H
DEC (HL)
Decrement the exponent in REG 1 at the location of the memory pointer in register pair HL
0901H
POP HL
Get the NMSB and the LSB of the dividend from the stack and put it in register pair HL
0902H-0903H
Jump back to 08C7H if the exponent in REG 1 isn’t equal to zero

0904H-0906H – DISPLAY OV ERROR MESSAGE

0904H-0906H
Display an ?OV ERROR

0907H-0913H – DOUBLE PRECISION MATH ROUTINE

0907H-0908H
LD A,FFH
Load Register A with a bit mask
0909H
2E
Z-80 Trick – See the note at 0134H for an explanation
090AH
XOR A
Zero A and clear the flags
090BH-090DH
LD HL,412DH
Load register pair HL with the address of the MSB in REG 2
090EH
LD C,(HL)
Load register C with the MSB of the value in REG 2 at the location of the memory pointer in register pair HL
090FH
INC HL
Increment the value of the memory pointer in register pair HL
0910H
XOR (HL)
Combine the value of the exponent in REG 2 at the location of the memory pointer in register pair HL with the bit mask in Register A
0911H
LD B,A
Load Register B with the adjusted exponent in Register A
0912H-0913H
LD L,00H
Load register L with a bit mask

0914H-0930H – SINGLE PRECISION MATH ROUTINE

0914H
LD A,B
Load Register A with the exponent in Register B
0915H
OR A
Check to see if the exponent in Register A is equal to zero
0916H-0917H
Jump to 0937H if the exponent in Register A is equal to zero
0918H
LD A,L
Load Register A with the bit mask in register L
0919H-091BH
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
091CH
XOR (HL)
Combine the value of the exponent at the location of the memory pointer in register pair HL with the bit mask in Register A
091DH
ADD A,B
Add the value of the exponent in Register B to the value of the exponent in Register A
091EH
LD B,A
Load Register B with the combined exponents in Register A
091FH
RRA
Shift the value of the combined exponents in Register A one place to the right
0920H
XOR B
Check to see if the Carry flag was set by combining the two exponents
0921H
LD A,B
Load Register A with the combined exponents value in Register B
0922H-0924H
Jump to 0936H if overflow has occurred
0925H-0926H
ADD 80H
Reload the new exponent into A and turn on bit 8
0927H
LD (HL),A
Save the value of the combined exponent in Register A as the exponent in REG 1 at the location of the memory pointer in register pair HL
0928H-092AH
Jump if the combined exponent in Register A is equal to zero
092BH-092DH
Go turn on the sign bit of the MSB in REG 1 and Register B and save the sign bits
092EH
LD (HL),A
Save the value in Register A at the location of the memory pointer in register pair HL
092FH
DEC HL
Decrement the memory pointer in register pair HL so that it points to the exponent in REG 1
093OH
RET
Return

0931H-093DH – SINGLE PRECISION MATH ROUTINE

0931H-0933H
Go check the value of the sign bit for the value in REG 1
0934H
CPL
Reverse the result of the sign bit test in Register A
0935H
POP HL
Get the value from the stack and put it in register HL
0936H
OR A
Set the flags according to the value of the sign bit test
0937H
POP HL
Get the value from the stack and put it in register pair HL
0938H-093AH
Jump to 0778H if the value in REG 1 is negative
093BH-093DH
If its not negative, jump to 07B2H

093EH-0954H – SINGLE PRECISION MATH ROUTINE

093EH-0940H
Call 09BF which loads the SINGLE PRECISION value in REG 1 into register pair BC/DE
0941H
LD A,B
Load Register A with the value of the exponent in Register B
0942H
OR A
Check to see if the exponent in Register A is equal to zero
0943H
RET Z
Return if the single precision value in register pairs BC and DE is equal to zero
0944H-0945H
ADD 02H
Multiply the value of the exponent in Register A by four
0946H-0948H
Display an ?OV ERROR if the adjusted exponent in Register A is too large
0949H
LD B,A
Load Register B with the adjusted exponent in Register A
094AH-094CH
Go add the original value in REG 1 to the adjusted value in register pairs BC and DE and return with the original result in REG 1 by calling the SINGLE PRECISION ADD routine at 0716H (which adds the single precision value in (BC/DE) to the single precision value in REG 1. The sum is left in REG 1)
094DH-094FH
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
0950H
INC (HL)
Increment the value of the exponent in REG 1 at the location of the memory pointer in register pair HL. REG 1 now holds the original value times ten
0951H
RET NZ
Return if the new value in REG 1 is in an acceptable range
0952H-0954H
Display an ?OV ERROR if the value of the exponent at the location of the memory pointer in register pair HL is too large

0955H-0963H – SINGLE PRECISION MATH ROUTINE

  • Checks if REG 1=0. If so, the Z flag will be set.
0955H-0957H
LD A,(4124H)
Load Register A with the value of the exponent in REG 1
0958H
OR A
Check to see if the exponent in Register A is equal to zero
0959H
RET Z
Return if the single precision value in REG 1 is equal to zero
095AH-095CH
LD A,(4123H)
Load Register A with the MSB of the single precision value in REG 1
095EH
CP 2FH
Reverse the value in Register A
095FH
RLA
Put the value of the sign bit in Register A into the Carry flag
0960H
SBC A,A
Make Register A equal to -1 if the sign bit is negative or a value of 0 if the sign bit is positive
0961H
RET NZ
Return if the single precision value in REG 1 is negative
0962H
INC A
Increment the value in Register A so that Register A will be equal to 1 if the single precision value in REG 1 is positive
0963H
RET
Return

0964H-0976H – SINGLE PRECISION MATH ROUTINE

0964H-0965H
LD B,88H
Load Register B with an exponent for an integer value
0966H-0968H
LD DE,0000H
Load register pair DE with zero
0969H-096BH
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
096CH
LD C,A
Load register C with the MSB of the integer value
096DH
LD (HL),B
Save the exponent in Register B in REG 1 at the location of the memory pointer in register pair HL
096EH-096FH
LD B,00H
Load Register B with zero
0970H
INC HL
Increment the memory pointer in register pair HL
0971H-0972H
LD (HL),80H
Save the sign value at the location of the memory pointer in register pair HL
0973H
RLA
Shift the value of the sign bit for the MSB in Register A into the Carry flag
0974H-0976H
Jump to 0762H

0977H-0989H – LEVEL II BASIC MATH ROUTINE
ABS

  • ABS routine (REG 1=ABS(REG 1)) input and output can be integer, single-precision or double-precision, depending on what is placed in the NTF (NTF=2, 4 or 8).
    A call to 0977H converts the value in Working Register Area 1 (WRAl) to its positive equivalent. The result is left in REG 1. If a negative integer greater than 2** 15 is encountered, it is converted to a single precision value. The data type or mode flag (40AFH) will be updated to reflect any change in mode.
  • NOTE: To use a ROM call to find ABS(X),store the value of X in 4121H-4122H (integer), in 4121H-4124H (single precision), or in 411DH and then H (double precision), and store the variable type (2, 4, or 8, respectively) in 40AFH. Then CALL 0977H. The result (in the same format as the input variable) is in the same locations in which the input variable was stored. If the input was an integer, the result is also in the HL register pair.
0977H-0979H
“ABS”
Go determine the sign of the current value in REG 1
097AH
RET P
Return if the value in REG 1 is positive
097BH
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
097CH-097EH
If that test showed INTEGER, jump to 0C5BH
097FH-0981H
If that test showed STRING, Display a ?TM ERROR message
0982H-0984H
“MVVAR”
LD HL,4123H
Load register pair HL with the address of the MSB in REG 1.

NEGATE function for single-precision values (REG 1=-REG 1). Only BC and DE are saved
0985H
LD A,(HL)
Load Register A with the MSB in REG 1 at the location of the memory pointer in register pair HL
0986H-0987H
XOR 80H
Set the sign bit in the MSB in Register A
0988H
LD (HL),A
Save the adjusted MSB in Register A in REG 1 at the location of the memory pointer in register pair HL
0989H
RET
Return

098AH-0993H – LEVEL II BASIC MATH ROUTINE
SGN

  • SGN function (REG 1=SGN(REG 1)). After execution, NTF=2 and REG 1=-l, 0 or 1 depending on sign and value of ACC before execution.
  • NOTE: To use a ROM call to find SGN(X), store the value of X in 4121H-4122H (integer), in 4121H-4124H (single precision), or in, s-4124H (double precision) and then store the variable type (2, 4, or 8, respectively) in 40AFH and then CALL 098AH. The result (in integer format) is in 4121H-4122H and in the HL register pair.
098AH-098CH
“SGN”
Go test the sign of the current value in REG 1
098DH
LD L,A
Load register L with the result of the sign test in Register A
098EH
RLA
Shift the sign bit in Register A into the Carry flag
098FH
SBC A,A
Adjust the value in Register A so that it will be equal to zero if the current value in REG 1 is positive and equal to -1 if the current value in REG 1 is negative
0990H
LD H,A
Save the adjusted value in Register A in register H
0991H-0993H
Jump to 0A9AH

0994H-09A3H – LEVEL II BASIC MATH ROUTINE

  • This routine checks the sign of the ACC. NTF must be set. After execution A register=00 if REG 1=0, A=01 if ACC > 0 or A=FFH if A < 1. The Flags are also valid.
0994H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0995H-0997H
If that test showed STRING, Display a ?TM ERROR message
0998H-099AH
Since P means string, single precision, or double precision; and if it was a string it would have jumped already, this line says jump to 0955H if the current value in REG 1 is single precision or double precision
099BH-099DH
LD HL,(4121H)
At this point, we know we have an integer. Load register pair HL with the integer value in REG 1
099EH
LD A,H
Load Register A with the MSB of the integer value in register H
099FH
OR L
Check to see if the integer value in REG 1 is equal to zero
09A0H
RET Z
Return if the integer value in REG 1 is equal to zero
09A1H
LD A,H
Load Register A with the MSB of the integer value in register H
09A2H-09A3H
Jump to 095FH

09A4H-09B0H – SINGLE PRECISION MATH ROUTINE
“LDSTSA”

  • Loads Single-precision value from ACC to stack ((SP)=ACC). To retrieve this value, POP BC followed by POP DE. A, BC and HL are unchanged by this function.
09A4H
“SSTAK”
EX DE,HL
Load register pair DE with the value in register pair HL
09A5H-09A7H
LD HL,(4121H)
Load register pair HL with the LSB and the NMSB of the single precision value in REG 1
09A8H
EX (SP),HL
Exchange the return address on the stack with the NMSB and the LSB of the single precision value in register pair HL
09A9H
PUSH HL
Save the return address in register pair HL on the stack
09AAH-09ACH
LD HL,(4123H)
Load register pair HL with the exponent and the MSB of the single precision value in REG 1
09ADH
EX (SP),HL
Exchange the return address on the stack with the exponent and the MSB of the single precision value in register pair HL
09AEH
PUSH HL
Save the return address in register pair HL on the stack
09AFH
EX DE,HL
Load register pair HL with the value in register pair DE
09B0H
RET
Return

09BlH-09BEH – SINGLE PRECISION MATH ROUTINE
“LDSAHL”

  • This routine loads four bytes from the location pointed to by HL, into the ACC. (REG 1=(HL)).
09B1H-09B3H
“SCOPY”
Call 09C2H (which loads a SINGLE PRECISION value pointed to by register pair HL into register pairs BC and DE)
09B4H
“DSTOR”
EX DE,HL
Load register pair HL with the NMSB and the LSB of the single precision value in register pair DE.

This routine loads REG 1 with the contents of the BC and DE register pairs. (REG 1=BCDE). BC and HL remain unaltered
09B5H-09B7H
LD (4121H),HL
Save the NMSB and the LSB of the single precision value in register pair HL in REG 1
09B8H
LD H,B
Load register H with the exponent of the single precision value in Register B
09B9H
LD L,C
Load register L with the MSB of the single precision value in register C
09BAH-09BCH
LD (4123H),HL
Save the exponent and the MSB of the single precision value in register pair HL in REG 1
09BDH
EX DE,HL
Load register pair HL with the value in register pair DE
09BEH
RET
Return

09BFH-09CAH – SINGLE PRECISION MATH ROUTINE
“LDRASA”

  • This routine is the opposite of the 09B4H routine. It loads four bytes from REG 1 (single-precision) into the BC and DE register pairs. (BCDE=ACC). A is unchanged.
09BFH-09C1H
LD HL,4121H
Load register pair HL with the starting address for a single precision value in REG 1
09C2H
“SGET”
LD E,(HL)
Load register E with the LSB of the single precision value in REG 1 at the location of the memory pointer in register pair HL.

This routine will load the BCDE register pairs with four bytes from the location pointed to by HL. (BCDE=(HL)),. With these types of data movements, the E register is loaded with the LSB and the B register. with the MSB
09C3H
INC HL
Increment the value of the memory pointer in register pair HL
09C4H
LD D,(HL)
Load register D with the NMSB of the single precision value in REG 1 at the location of the memory pointer in register pair HL
09C5H
INC HL
Increment the value of the memory pointer in register pair HL
09C6H
LD C,(HL)
Load register C with the MSB of the single precision value in REG 1 at the location of the memory pointer in register pair HL
09C7H
INC HL
Increment the value of the memory pointer in register pair HL
09C8H
LD B,(HL)
Load Register B with the exponent of the single precision value in REG 1 at the location of the memory pointer in register pair HL
09C9H
INC HL
Increment the value of the memory pointer in register pair HL
09CAH
RET
Return

09CBH-09DlH – SINGLE PRECISION MATH ROUTINE
“LDHLSA”

  • This routine is the opposite of the 9B1H routine. It loads four bytes from REG 1 to the memory location pointed to by HL. ((HL)=ACC).
09CBH-09CDH
LD DE,4121H
Load register pair DE with the starting address for a single precision value in REG 1 (whci is at 16673)
09CEH-09CFH
LD B,04H
Load Register B with the number of bytes to be moved for a single precision value.

Data move routine. This moves four bytes from the location pointed to by DE into the location pointed to by HL. ((HL)=(DE))
09D0H-09D1H
Jump to 09D7H (which is the GENERAL PURPOSE MOVE routine and moves the contents of the B Register Bytes from the address in DE to the address in HL)

09D2H-09DEH – MOVE VALUE POINTED TO BY HL TO THE LOCATION POINTED TO BY DE
“LDDEHL”

  • This is the VARIABLE MOVE Routine which moves the number of bytes specified in the type flag (40AFH) from the address in DE to the address in HL. Uses A, DE and HL.
09D2H
EX DE,HL
Exchange the value in register pair HL with the value in register pair DE.

Data move routine. The location pointed to by DE is loaded with bytes from the location pointed to by HL. The number of bytes moved is determined by the value in the NTF. ((DE)=(HL))
09D3H-09D5H
“LDHLDE”
LD A,(40AFH)
Load Register A with the current value of the number type flag (which is in 40AFH).

This routine is similar to 9D2H above. The only difference is that it moves data in the opposite direction. ((HL) = (DE)).
Note: 40AFH holds Current number type flag
09D6H
“MOVEA”
LD B,A
Load Register B with the number of bytes to be moved in Register A.

This routine is the same as 9D3H except that the number of bytes moved depends on the value in the A register ((HL) = (DE))
09D7H
“MOVEB”
LD A,(DE)
Load Register A with the value at the location of the memory pointer in register pair DE.

This routine is the same as 9D6H except that the number of bytes shifted is determined by the value in the B register ((HL)=(DE)).
This is the GENERAL PURPOSE MOVE routine and moves the contents of the B Register Bytes from the address in DE to the address in HL)
09D8H
LD (HL),A
Save the value in Register A at the location of the memory pointer in register pair HL
09D9H
INC DE
Increment the value of the memory pointer in register pair DE
09DAH
INC HL
Increment the value of the memory pointer in register pair HL
09DBH
DEC B
Decrement the value of the byte counter in Register B
09DCH-09DDH
Loop until all of the bytes have been moved
09DEH
RET
Return

09DFH-09F3H – SINGLE PRECISION MATH ROUTINE

09DFH-09E1H
LD HL,4123H
Load register pair HL with the address of the MSB of the value in REG 1
09E2H
LD A,(HL)
Load Register A with the MSB of the value in REG 1 at the location of the memory pointer in register pair HL
09E3H
RLCA
Move the value of the sign bit in Register A into the Carry flag
09E4H
SCF
Set the Carry flag
09E5H
RRA
Turn off the sign bit in Register A by moving the value of the Carry flag into Register A and moving the previous value of the sign bit from bit 0 of Register A into the Carry flag
09E6H
LD (HL),A
Save the adjusted MSB in Register A in REG 1 at the location of the memory pointer in register pair HL
09E7H
CCF
Invert the value of the sign bit in the Carry flag
09E8H
RRA
Move the inverted sign bit from the Carry flag into Register A
09E9H
INC HL
Increment the value of the memory pointer in register pair HL
09EAH
INC HL
Increment the value of the memory pointer in register pair HL
09EBH
LD (HL),A
Save the value in Register A at the location of the memory pointer in register pair HL
09ECH
LD A,C
Load Register A with the MSB of the single precision value in register C
09EDH
RLCA
Move the value of the sign bit in Register A into the Carry flag
09EEH
SCF
Set the Carry flag
09EFH
RRA
Turn on the sign bit in Register A by moving the value of the Carry flag into Register A and moving the previous value of the sign bit from bit 0 of Register A into the Carry flag
09F0H
LD C,A
Load register C with the adjusted MSB in Register A
09F1H
RRA
Move the value of the sign bit from the Carry flag into Register A
09F2H
XOR (HL)
Combine the value of the sign bit for the single precision value in Register A with the value of the sign bit for the single precision value at the location of the memory pointer in register pair HL
09F3H
RET
Return

09F4H-09FBH – LEVEL II BASIC MATH ROUTINE

  • This routine is used by the double-precision logic. It moves a number of bytes (the number depending on the value stored in the NTF) from the AACC into the ACC. ((REG 1)=(AACC)).
09F4H-09F6H
LD HL,4127H
Load register pair HL with the starting address of REG 2.
Note: 4127H-412EH holds REG 2
09F7H-09F9H
“MVSAHL”
LD DE,09D2H
Load register pair DE with the return address
09FAH-09FBH
Jump to 0A02 (which is 2562)

09FCH-0A0BH – LEVEL II BASIC MATH ROUTINE

  • This is the opposite of 9F4H. ((AACC)=(REG 1)).
09FCH-09FEH
“MVALT”
LD HL,4127H
Load register pair HL with the starting address of REG 2 (which is 16679).
Note: 4127H-412EH holds REG 2
09FFH-0A01H
LD DE,09D3H
Load register pair DE with the return address
0A02H
PUSH DE
Save the return address in register pair DE on the stack
0A03H-0A05H
LD DE,4121H
Load register pair HL with the starting address for a single precision value in REG 1
0A06H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0A07H
RET C
If that test is anything other than double precision, return out of this subroutine
0A08H-0A0AH
LD DE,411DH
Load register pair DE with the starting address of REG 1.
Note: 411DH-4124H holds REG 1
0A0BH
RET
Return

0A0CH-0A25H – SINGLE PRECISION COMPARE
“CPSP”

  • Single-precision compare. Compares REG 1 with the contents of BCDE registers. After execution of this routine, the A register will contain: A=0 if REG 1=BCDE, A=1 if ACC>BCDE or A=FFH if ACC<BCDE.
  • NOTE: To use a ROM call to compare two single precision numbers, store the first input in registers BCDE, the second input in 4121H-4124H and then CALL 0A0CH. If the numbers are equal, the Z (zero) flag will be set. If they are not equal, the Z flag will be turned off. If the first input number is the smaller, the S (sign) and C (carry) flags will also be turned off. If the second input number is the smaller, the S and C flags will both be set.
0A0CH
LD A,B
Load Register A with the value of the exponent in Register B
0A0DH
OR A
Check to see if the exponent in Register A is equal to zero
0A0EH-0A10H
Jump if the exponent in Register A is equal to zero
0A11H-0A13H
LD HL,095EH
Load register pair HL with the return address
0A14H
PUSH HL
Save the return address in register pair HL on the stack
0A15H-0A17H
Go check the signs of the single precision numbers
0A18H
LD A,C
Load Register A with the MSB of the single precision value in register C
0A19H
RET Z
Return if the signs of the single precision values aren’t equal
0A10H-0A1CH
LD HL,4123H
Load register pair HL with the address of the MSB in Register A
0A1DH
XOR (HL)
Combine the MSB in REG 1 at the location of the memory pointer in register pair HL with the MSB in Register A
0A1EH
LD A,C
Load Register A with the MSB in register C
0A1FH
RET M
Return if the MSBs don’t match
0A20H-0A22H
Go compare the single precision values
0A23H
RRA
Move the value of the Carry flag from the comparison into Register A
0A24H
XOR C
Combine the value of the MSB of the single precision value in register C with the value in Register A
0A25H
RET
Return

0A26H-0A38H – SINGLE PRECISION COMPARISON ROUTINE

0A26H
INC HL
Increment the value of the memory pointer in register pair HL so that it points to the exponent in REG 1
0A27H
LD A,B
Load Register A with the value of the exponent for the single precision value in Register B
0A28H
CP (HL)
Check to see if the exponent for the single precision value in REG 1 at the location of the memory pointer in register pair HL is the same as the value of the exponent for the single precision value in Register A
0A29H
RET NZ
Return if the value of the exponent in REG 1 isn’t the same as the value of the exponent in Register A
0A2AH
DEC HL
Decrement the value of the memory pointer in register pair HL
0A2BH
LD A,C
Load Register A with the MSB for the single precision value in register C
0A2CH
CP (HL)
Check to see if the MSB for the single precision value in REG 1 at the location of the memory pointer in register pair HL is the same as the value of the MSB for the single precision value in Register A
0A2DH
RET NZ
Return if the value of the MSB in REG 1 isn’t the same as the value of the MSB in Register A
0A2EH
DEC HL
Decrement the value of the memory pointer in register pair HL
0A2FH
LD A,D
Load Register A with the NMSB of the single precision value in register D
0A30H
CP (HL)
Check to see if the NMSB for the single precision value in REG 1 at the location of the memory pointer in register pair HL is the same as the value of the NMSB for the single precision value in Register A
0A31H
RET NZ
Return if the value of the NMSB in REG 1 isn’t the same as the value of the NMSB in Register A
0A32H
DEC HL
Decrement the value of the memory pointer in register pair HL
0A33H
LD A,E
Load Register A with the LSB of the single precision value in register E
0A34H
SUB (HL)
Check to see if the LSB for the single precision value in REG 1 at the location of the memory pointer in register pair HL is the same as the value of the LSB for the single precision value in Register A
0A35H
RET NZ
Return if the value of the LSB in REG 1 isn’t the same as the value of the LSB in Register A
0A36H
POP HL
Get the value from the stack and put it in register pair HL
0A37H
POP HL
Get the value from the stack and put it in register pair HL
0A3BH
RET
Return

0A39H-0A48H – INTEGER COMPARE

  • Integer compare. Compares HL with DE. After execution, A=0 if HL=DE, A=1 if HL>DE or A=FFH if HL<DE. The S and Z flags are valid.
  • NOTE: To use a ROM call to compare two integers, store the first input in DE, the second in HL and then CALL 0A39H. If the numbers are equal, the Z (zero) flag will be set. If they are not equal, the Z flag will be turned off. If the first input number is the smaller, the S (sign) and C (carry) flags will also be turned off. If the second input number is the smaller, the S and C flags will both be set.
0A39H
LD A,D
Load Register A with the MSB of the integer value in register D
0A3AH
XOR H
Check to see if the sign bit for the MSB of the integer value in register H is the same as the sign bit for the MSB for the integer value in Register A
0A3BH
LD A,H
Load Register A with the MSB of the integer value in register H
0A3CH-0A3EH
Jump if the sign bits for the integer values aren’t equal
0A3FH
CP D
Check to see if the MSB for the integer value in register D is the same as the MSB for the integer value in Register A
0A40H-0A42H
Jump if the MSB for the integer value in register D isn’t the same as the MSB for the integer value in Register A
0A33H
LD A,L
Load Register A with the LSB of the integer value in register L
0A44H
SUB E
Check to see if the LSB for the integer value in register E is the same as the LSB for the integer value in Register A
0A45H-0A47H
Jump if the LSB for the integer value in register E isn’t the same as the LSB for the integer value in Register A
0A48H
RET
Return

0A49H-0A77H – DOUBLE PRECISION COMPARE

  • Double-precision compare. Compares REG 1 with the AACC. After execution the A register will contain: A=0 if REG 1=AACC, A=1 if ACC > AACC or A=FFH if ACC < AACC. S and Z flags are valid.
0A49H-0A4BH
LD HL,4127H
Load register pair HL with the starting address of REG 2.
Note: 4127H-412EH holds REG 2
0A4CH-0A4EH
Go move the double precision value pointed to by register pair DE to REG 2
0A4FH-0A51H
LD DE,412EH
Load register pair DE with the address of the exponent in REG 2
0A52H
LD A,(DE)
Load Register A with the exponent for the double precision value in REG 2 at the location of the memory pointer in register pair DE
0A53H
OR A
Check to see if the double precision value in REG 2 is equal to zero
0A54H-0A56H
Jump if the double precision value in REG 2 is equal to zero
0A57H-0A59H
LD HL,095EH
Load register pair HL with the return address
0A5AH
PUSH HL
Save the return address in register pair HL on the stack
0A5BH-0A5DH
Go check to see if the double precision value in REG 1 is equal to zero
0A5EH
DEC DE
Decrement the value of the memory pointer in register pair DE
0A5FH
LD A,(DE)
Load Register A with the MSB of the double precision value in REG 2 at the location of the memory pointer in register pair DE
0A60H
LD C,A
Load register C with the MSB of the double precision value in REG 2 in Register A
0A61H
RET Z
Return if the double precision value in REG 1 is equal to zero
0A62H-0A64H
LD HL,4123H
Load register pair HL with the address of the MSB of the double precision value in REG 1
0A65H
XOR (HL)
Check to see if the sign bit for the MSB of the double precision value in REG 1 at the location of the memory pointer in register pair HL is the same as the sign bit for the MSB of the double precision value in REG 2 in Register A
0A66H
LD A,C
Load Register A with the MSB of the double precision value in REG 2 in register C
0A67H
RET M
Return if the sign bits for the double precision values in REG 1 and REG 2 aren’t the same
0A68H
INC DE
Increment the value of the memory pointer in register pair DE
0A69H
INC HL
Increment the value of the memory pointer in register pair HL
0A6AH-OA6BH
LD B,08H
Load Register B with the number of bytes to be compared
0A6CH
LD A,(DE)
Load Register A with the value at the location of the memory pointer in register pair DE
0A6DH
SUB (HL)
Check to see if the value in Register A is the same as the value at the location of the memory pointer in register pair HL
0A6EH-0A70H
Jump back to 0A23H if the value in Register A isn’t the same as the value at the location of the memory pointer in register pair HL
0A71H
DEC DE
Decrement the value of the memory pointer in register pair DE
0A72H
DEC HL
Decrement the value of the memory pointer in register pair HL
0A73H
DEC B
Decrement the number of bytes remaining to be compared in Register B
0A74H-0A75H
Loop until all of the bytes have been compared
0A76H
POP BC
Get the value from the stack and put it in register pair BC
0A77H
RET
Return

0A78H-0A7EH – DOUBLE PRECISION COMPARE
“CPDP”

  • Double-precision compare. This compare is the opposite of the A4FH compare. It compares the AACC with the ACC. (Remember that a compare is actually a subtraction that is never executed therefore a compare can be done in two ways with the same values. (A-B and B-A)). The results are the same as the A4FH routine.
  • NOTE: To use a ROM call to compare two double precision number, store the first input in 411DH-4124H, and store the second input in 4127H-412EH and then CALL 0A78H. If the numbers are equal, the Z (zero) flag will be set. If they are not equal, the Z flag will be turned off. If the first input number is the smaller, the S (sign) and C (carry) flags will also be turned off. If the second input number is the smaller, the S and C flags will both be set.
0A78H-0A7AH
Go compare the double precision value in REG 2 to the double precision value in REG 1
0A7BH-0A7DH
Jump if the double precision value in REG 1 and the double precision value in REG 2 aren’t the same
0A7EH
RET
Return

0A7FH-0AB0H – LEVEL II BASIC CINT ROUTINE

  • CINT routine. Takes a value from ACC, converts it to an integer value and puts it back into the ACC. On completion, the HL register pair contains the LSB of the integer value, and the NTF contains 2 (Integer=2). If NTF=3 (string) a TM ERROR will be generated and control will be passed to BASIC.
0A7FH
“CINT”
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0A80H-0A82H
LD HL,(4121H)
Load register pair HL with the integer value in REG 1
0A83H
RET M
If that test showed we have an INTEGER, then return out of this subroutine
0A84H-0A86H
If that test showed we have a STRING, Display a ?TM ERROR message
0A87H-0A89H
If that test shows we have DOUBLE PRECISION, call 0AB9H to convert the number to single precision
  • NOTE: To use a ROM call to call the CINT routine, store the single precision input variable in 4121H-4124H and then call to 0A8AH and bypass all the foregoing. After the call, the integer result would be in 4121H-4122H and in the HL register pair. Too big a number will generate a ?OV Error.
0A8AH-0A8CH
LD HL,07B2H
Load register pair HL with the return address
0A8DH
PUSH HL
Save the return address in register pair HL on the stack
0A8EH-0A90H
LD A,(4124H)
Load Register A with the exponent for the single precision value in REG 1
0A91H-0A92H
CP 90H
Check to see if the exponent for the single precision value in REG 1 in Register A indicates more than 16 bits of precision
0A93H-0A94H
Jump if the exponent for the single precision value in REG 1 in Register A indicates more than 16 bits of precision
0A95H-0A97H
Go convert the single precision value in REG 1 to an integer and return with the integer value in register pair DE
0A98H
EX DE,HL
Load register pair HL with the integer value in register pair DE
0A99H
POP DE
Get the value from the stack and put it in register pair DE
0A9AH-0A9CH
“ISTOR”
LD (4121H),HL
Save the integer value in register pair HL as the current value in REG 1.

This is the routine that returns the value in the HL register pair to the BASIC program that called it. In effect it moves the content of HL into REG 1 (ACC = HL)
0A9DH-0A9EH
“FLAGIN”
LD A,02H
Load Register A with an integer number type flag.

Set NTF to Integer (2). (A=used)
0A9FH-0AA1H
LD (40AFH),A
Save the integer number type flag in Register A as the current value of the number type flag.
Note: 40AFH holds Current number type flag
0AA2H
RET
Return
0AA3H-0AA5H
LD BC,9080H
Load register pair BC with the exponent and the MSB of a single precision value
0AA6H-0AA8H
LD DE,0000H
Load register pair DE with the NMSB and the LSB of a single precision value. Register pairs BC and DE now hold a single precision value equal to -32768
0AA9H-0AABH
Call the SINGLE PRECISION COMPARISON routine at 0A0CH.

NOTE: The routine at 0A0CH algebraically compares the single precision value in BC/DE to the single precision value REG 1.
The results are stored in A as follows:
  • A=0 if REG 1 = BCDE
  • A=1 if REG 1>BCDE; and
  • A=FFH if REG 1<BCDE.
0AACH
RET NZ
Display an ?OV ERROR if the value in REG 1 isn’t equal to -32768
0AADH
LD H,C
Load register H with the MSB of the single precision value in register C
0AAEH
LD L,D
Load register L with the NMSB of the single precision value in register D
0AAFH-0AB0H
Jump to 0A99H

0AB1H-0ACBH – LEVEL II BASIC CSNG ROUTINE
“CSASP”

  • CSNG routine. Takes value from ACC and converts it to single-precision. The result is put in ACC and NTF contains 4.
0AB1H
“CSNG”
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0AB2H
RET PO
If that test shows we have SINGLE PRECISION, return out of this subroutine
0AB3H-0AB5H
If that test shows we have an INTEGER, jump to 0ACCH
0AB6H-0AB8H
If that test shows we have a STRING, display a ?TM ERROR
0AB9H-0ABBH
At this point, we have a DOUBLE PRECISION number, so call 09BF which loads the SINGLE PRECISION value in REG 1 (which is currently the most significant four bytes of the double precision value in REG 1) into register pair BC/DE
0ABCH-0ABEH
Go set the current number type flag to single precision
0ABFH
LD A,B
Load Register A with the exponent of the double precision value in Register B
0AC0H
OR A
Check to see if the double precision value in REG 1 is equal to zero
0AC1H
RET Z
Return if the double precision value in REG 1 is equal to zero
0AC2H-0AC4H
Go turn on the most significant bit of the single precision value in REG 1
0AC5H-0AC7H
LD HL,4120H
Load register pair HL with the address of the most significant byte chopped off the double precision value
0AC8H
LD B,(HL)
Loaded Register B with the most significant byte chopped off the double precision value at the location of the memory pointer in register pair HL
0AC9H-0ACBH
Jump to 0796H

0ACCH-0ADAH – LEVEL II BASIC MATH ROUTINE
“CHGIS”

  • Convert Integer to Single Precision.
  • Note: If you wanted to convert integer to single precision via a ROM call, you would store the integer input variable in 4121H-4122H and then call to 0ACCH. The result (as a single precision number) will be in 4121H-4124H.
0ACCH-0ACEH
LD HL,(4121H)
Load register pair HL with the integer value at the location of an integer storage in REG 1
0ACFH-0AD1H
Go set the current number type flag to single precision
0AD2H
LD A,H
Load Register A with the MSB of the integer value in register H
0AD3H
LD D,L
Load register D with the LSB of the integer value in register L
0AD4H-0AD5H
LD E,00H
Zero register E
0AD6H-0AD7H
LD B,90H
Load Register B with the initial maximum exponent
0AD8H-0ADAH
Jump to 0969H

0ADBH-0AEDH – LEVEL II BASIC CDBL ROUTINE
“CSADP”

  • CDBL routine. Takes a value from ACC and converts it to double-precision. The result will be in ACC and NTF will be 8.
0ADBH
“CDBL”
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0ADCH
RET NC
If that test shows we have a DOUBLE PRECISION number, return out of the subroutine
0ADDH-0ADFH
If that test shows we have a STRING, Display a TM ERROR message
0AE0H-0AE2H
If that test shows we have an INTEGER, then go to 0ACCH to convert it to SINGLE PRECISION.
0AE3H-0AE5H
LD HL,0000H
So now we know we have a SINGLE PRECISION value. Load register pair HL with zero
0AE6H-0AE8H
LD (411DH),HL
Save the value in register pair HL as the first and second bytes of REG 1.
Note: 411DH-4124H holds REG 1
0AE9H-0AEBH
LD (411FH),HL
Save the value in register pair HL as the third and fourth bytes of REG 1
0AECH-0AEDH
“FLAGDP”
LD A,08H
Load Register A with a double precision number type flag

0AEEH-0AF3H – LEVEL II BASIC MATH ROUTINE

0AEEH
01
Z-80 Trick – See the note at 0134H for an explanation
0AEFH-0AF0H
“FLAGSP”
LD A,04H
Load Register A with a single precision number type flag (of 4)
0AF1H-0AF3H
Jump away to 0A9FH to save the value in Register A as the current number type flag

0AF4H-0AFAH – LEVEL II BASIC MATH ROUTINE

  • This routine calls 20H (RST 20H) and returns if NTF=3 (string) else if NTF is not 3 then it generates a TM ERROR. BC, DE, and HL are saved.
0AF4H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0AF5H
RET Z
If that test shows we have a STRING, return out of the subroutine
0AF6H-0AF7H
LD E,18H
Load register E with a TM ERROR code.

This is the entry point for the TM ERROR
0AF8H-0AFAH
Display a TM ERROR message if the current value in REG 1 isn’t a string

0AFBH-0B1EH – LEVEL II BASIC MATH ROUTINE

  • This routine will reset the BC and DE register pairs if the A register contains 0. (XOR A before calling this routine).
0AFBH
LD B,A
Load Register B with the exponent of the single precision number in Register A
0AFCH
LD C,A
Load register C with the exponent of the single precision number in Register A
0AFDH
LD D,A
Load register D with the exponent of the single precision number in Register A
0AFEH
LD E,A
Load register E with the exponent of the single precision number in Register A
0AFFH
OR A
Check to see if the single precision number in REG 1 is equal to zero
0B00H
RET Z
Return if the single precision value in REG 1 is equal to zero
0B01H
PUSH HL
Save the value in register pair HL on the stack
0B02H-0B04H
Call 09BF which loads the SINGLE PRECISION value in REG 1 into register pair BC/DE
0B05H-0B07H
Go turn on the sign bit of the single precision value in register pairs BC and DE
0B08H
XOR (HL)
Set the sign bit according to the sign of the value at the location of the memory pointer in register pair HL
0B09H
LD H,A
Load register H with the value of the sign in Register A
0B0AH-0B0CH
Go decrement the single precision value in register pairs BC and DE if the sign of the value is negative
0B0DH-0B0EH
LD A,98H
Load Register A with the maximum exponent
0B0FH
SUB B
Figure the number of bits to be shifted by subtracting the exponent in Register B from the exponent in Register A
0B10H-0B12H
Go shift the single precision value in register pairs BC and DE
0B13H
LD A,H
Load Register A with the value of the sign in register H
0B14H
RLA
Put the sign bit into the Carry flag
0B15H-0B17H
Go bump the value in register pairs BC and DE if the original number was negative
0B18H-0B19H
LD B,00H
Load Register B with an exponent
0B1AH-0B1CH
Go make the integer negative if the original number was negative. Return with the integer value in register pair DE
0B1DH
POP HL
Get the value from the stack and put it in register pair HL
0B1EH
RET
Return

0BlFH-0B25H – LEVEL II BASIC MATH ROUTINE

0B1FH
DEC DE
Decrement the NMSB and the LSB of the single precision value in register pair DE
0B20H
LD A,D
Load Register A with the value of the NMSB for the single precision value in register D
0B21H
AND E
Combine the LSB of the single precision value in register E with the NMSB of the single precision value in Register A
0B22H
INC A
Increment the combined value in Register A
0B23H
RET NZ
Return if the NMSB and the LSB of the single precision value in register pair DE isn’t equal to FFFFH
0B24H
DEC BC
Decrement the value of the exponent and the MSB of the single precision value in register pair BC
0B25H
RET
Return

0B26H-0B58H – LEVEL II BASIC FIX ROUTINE
“FIX”

  • FIX routine. Takes a value from ACC and converts it to an integer value. The result will be in ACC. NTF will be 2 if value is smaller than 32767 else it will be 4. An error will be generated if NTF=3 (string).
    A call to 0B26H unconditionally truncates the fractional part of a floating point number in REG 1. The result is stored in WRAl and the type flag is set to integer.
  • Note: If you wanted to call the FIX routine via a ROM call, you would store the single-precision input variable in 4121H-4124H, then put a 4 into 40AFH to flag as single precision, and then call to 0B26H. If the result can be an integer, it will be in 4121H-4122H and in the HL register pair. If single precision, the result will be in 4121H-4124H. If double precision, in 411DH-4124H. In all cases 40AFH will have the data mode flag as 2, 4, or 8, accordingly.
0B26H
“FIX”
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0B27H
RET M
If that test shows we have an INTEGER, return out of the subroutine
0B28H-0B2AH
Go check the sign of the current value in REG 1
0B2BH-0B2DH
If the current value in REG 1 is positive, jump to the RETURN INTEGER (INT[N]) routine at 0B37H (which returns the integer portion of a floating point number. If the value is positive, the integer portion is returned. If the value is negative with a fractional part, it is rounded up before truncation. The integer portion is left in REG 1. The mode flag is updated.)
0B2EH-0B30H
Gosub to 0982H to convert the current value in REG 1 to positive
0B31H-0B33H
Now that REG 1 is positive, call the RETURN INTEGER (INT[N]) routine at 0B37H (which returns the integer portion of a floating point number. If the value is positive, the integer portion is returned. If the value is negative with a fractional part, it is rounded up before truncation. The integer portion is left in REG 1. The mode flag is updated.)
0B34H-0B36H
Jump back to 097BH (which is in the middle of the ABS(x) routine

0B37H – LEVEL II BASIC INT( ROUTINE

A call to 0B37H returns the integer portion of a floating point number. If the value is positive, the integer portion is returned. If the value is negative with a fractional part, it is rounded up before truncation. The integer portion is left in REG 1. The mode flag is updated.

0B37H
“INT”
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0B38H
RET M
If that test shows we have an INTEGER, return out of this subroutine
0B39H-0B3AH
Jump if the current value in REG 1 is double precision
0B3BH-0B3CH
Display a ?TM ERROR if the current value in REG 1 isa string

Note: If you wanted to call the INT routine via a ROM call, you would store the single precision input variable in 4121H-4124H, put a 4 into 40AFH (to flag as single precision), and then call 0B3DH and bypass all the foregoing. After the call, the integer result would be in 4121H-4122H and in the HL register pair IF the absolute value of the input did not exceed 32767. Otherwise it will be in 4121H-4124H in single precision format, and 40AF will be a 2 for integer or 4 for single precision..

0B3DH-0B3FH
Go convert the single precision value in REG 1 to an integer
0B40H-0B42H
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
0B43H
LD A,(HL)
Load Register A with the value of the exponent in REG 1 at the location of the memory pointer in register pair HL
0B44H-0B45H
CP 98H
Check to see if there is more than 24 bits of precision used by the current value in REG 1
0B46H-0B48H
LD A,(4121H)
Load Register A with the LSB of the single precision number in REG 1
0B49H
RET NC
Return if more than 24 bits of precision is used by the single precision value in REG 1
0B4AH
LD A,(HL)
Load Register A with the exponent of the single precision number in REG 1
0B4BH-0B4DH
Go convert the single precision number in REG 1 to an integer
0B4EH-0B4FH
LD (HL),98H
Save an exponent in REG 1
0B50H
LD A,E
Load Register A with the LSB of the integer value in register E
0B51H
PUSH AF
Save the LSB of the integer value in Register A on the stack
0B52H
LD A,C
Load Register A with the value in register C
0B53H
RLA
Move the sign bit in Register A into the Carry flag
0B54H-0B56H
Go make the number in REG 1 single precision
0B57H
POP AF
Get the LSB of the single precision value from the stack and put it in Register A
0B58H
RET
Return

0B59H-0B9DH – LEVEL II BASIC MATH ROUTINE

0B59H-0B5BH
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
0B5CH
LD A,(HL)
Load Register A with the value of the exponent for the double precision number in REG 1 at the location of the memory pointer in register pair HL
0B5DH-0B5EH
CP 90H
Check to see if the double precision number in REG 1 uses more or less than 16 bits of precision (which is 0001 0100 0100 in binary)
0B5FH-0B61H
If the double precision value in REG 1 uses less than 16 bits of precision, jump to the CONVERT TO INTEGER routine at 0A7F (where the contents of REG 1 are converted from single or double precision to integer and stored in HL)
0B62H-0B63H
Jump forward to 0B78H if the double precision number in REG 1 uses more than 16 bits of precision
0B64H
LD C,A
Load register C with the exponent for the double precision number in Register A
0B65H
DEC HL
Decrement the value of the memory pointer in register pair HL
0B66H
LD A,(HL)
Load Register A with the MSB of the double precision value in REG 1 at the location of the memory pointer in register pair HL
0B67H-0B68H
XOR 80H
Complement the value of the sign bit in Register A (which is 1000 0000)
0B69H-0B6AH
LD B,06H
Load Register B with the number of bytes to be checked
0B6BH
DEC HL
Decrement the value of the memory pointer in register pair HL
0B6CH
OR (HL)
Combine the value at the location of the memory pointer in register HL with the value in Register A
0B6DH
DEC B
Decrement the byte counter in Register B
0B6EH-0B6FH
Loop until all of the bytes have been checked
0B70H
OR A
Check to see if the double precision value in REG 1 is equal to a -32768
0B71H-0B73H
LD HL,8000H
Load register pair HL with a negative zero
0B74H-0B76H
Jump back to 0A9AH if the double precision value in REG 1 is a -32768
0B77H
LD A,C
Load Register A with the exponent for the double precision value in register C
0B78H-0B79H
CP B8H
Check to see if more than 56 bits of precision has been used for the double precision value in REG 1
0B7AH
RET NC
Return if more than 56 bits of precision have been used for the double precision value in REG 1
0B7BH
PUSH AF
Save the exponent in Register A on the stack
0B7CH-0B7EH
Gosub to 09BF which loads most significant four bytes of the double precision value in REG 1 into register pair BC/DE
0B7FH-0B81H
Gosub to 09DFH to turn on the sign bit and return with the value of the sign
0B82H
XOR (HL)
Combine the value at the location of the memory pointer in register pair HL with the result of the sign test in Register A
0B83H
DEC HL
Decrement the value of the memory pointer in register pair HL
0B84H-0B85H
LD (HL),B8H
Save an exponent at the location of the memory pointer in register HL
0B86H
PUSH AF
Save the value of the sign test in Register A on the stack
0B87H-0B89H
Go adjust the number in REG 1 if it’s negative
0B8AH-0B8CH
LD HL,4123H
Load register pair HL with the address of the MSB in REG 1
0B8DH-0B8EH
LD A,B8H
Load Register A with the maximum value of an exponent
0B8FH
SUB B
Subtract the value of the exponent at the location of the memory pointer in register pair HL from the value in Register A
0B90H-0B92H
Go adjust the value in REG 1
0B93H
POP AF
Get the value of the sign test from the stack and put it in Register A
0B94H-0B96H
Go adjust the value in REG 1 if it’s negative
0B97H
XOR A
Zero Register A
0B98H-0B9AH
LD (411CH),A
Zero memory location 16668.
Note: 411CH holds Used by floating point routines
0B9BH
POP AF
Get the value of the original exponent test from the stack and put it in register pair AF
0B9CH
RET NC
Return if more than 56 bits are used by the double precision number
0B9DH-0B9FH
Jump to 0CD8H

0BA0H-0BA9H – LEVEL II BASIC MATH ROUTINE

0BA0H-0BA2H
LD HL,411DH
Load register pair HL with the starting address of REG 1.
Note: 411DH-4124H holds REG 1
0BA3H
LD A,(HL)
Load Register A with the value at the location of the memory pointer in register pair HL
0BA4H
DEC (HL)
Decrement the value at the location of the memory pointer in register pair HL
0BA5H
OR A
Check to see if the value in Register A is equal to zero
0BA6H
INC HL
Decrement the value of the memory pointer in register pair HL
0BA7H-0BA8H
Loop until the value at the location of the memory pointer in register pair HL is equal to a nonzero value
0BA9H
RET
Return

0BAAH-0BC6H – LEVEL II BASIC MATH ROUTINE

0BAAH
PUSH HL
Save the value in register pair HL on the stack
0BABH-0BADH
LD HL,0000H
Load register pair HL with zero
0BAEH
LD A,B
Load Register A with the MSB of the integer value in Register B
0BAFH
OR C
Combine the LSB of the integer value in register C with the MSB of the integer value in Register A
0BB0H-0BB1H
Jump if the integer value in register pair BC is equal to zero
0BB2H-0BB3H
LD A,10H
Load Register A with the counter value (which is 16)
0BB4H
ADD HL,HL
Multiply the result in register pair HL by two
0BB5H-0BB7H
Display a BS ERROR message if the result in register pair HL has overflowed
0BB8H
EX DE,HL
Exchange the integer value in register pair DE with the result in register pair HL
0BB9H
ADD HL,HL
Multiply the integer value in register pair HL by two
0BBAH
EX DE,HL
Exchange the result in register pair DE with the integer value in register pair HL
0BBBH-0BBCH
Jump if the most significant bit in the integer value in register DE wasn’t set
0BBDH
ADD HL,BC
Add the integer value in register pair BC to the result in register pair HL
0BBEH-0BC0H
Display a BS ERROR message if the result in register pair HL has overflowed
0BC1H
DEC A
Decrement the counter in Register A
0BC2H-0BCJH
Loop until the multiplication has been completed
0BC4H
EX DE,HL
Load register pair DE with the result in register pair HL
0BC5H
POP HL
Get the value from the stack and put it in register pair HL
0BC6H
RET
Return

0BC7H-0BD1H – INTEGER SUBTRACTION
“SUBINT”

  • Integer subtract. (REG 1=DE-HL) The result is returned in both REG 1 and the HL register pair.
    Subtracts the value in DE from the value in HL. The difference is left in the HL register pair. DE is preserved. In the event of underflow, both values are converted to single precision and the subtraction is repeated. The result is left in REG 1 and the mode flag is updated accordingly.
  • Note: If you wanted to subtract 2 integers via a ROM call, store one into DE and the subtrahend in HL (i.e., to do 26-17, DE gets 26), and then call 0BC7H. The integer result will be stored in 4121H-4122H approximately 210 microseconds later, and 40AFH will be set to 2 (to flag it as an integer). If there is an overflow, it will be converted to single precision (with 40AFH being a 4 in that case) and will be stored in 4121H-4124H.
0BC7H
“ISUB”
LD A,H
Load Register A with the MSB of the integer value in register H
0BC8H
RLA
Put the value of the sign bit into the Carry flag
0BC9H
SBC A,A
Adjust Register A according to the value of the sign bit
0BCAH
LD B,A
Load Register B with the result of the sign test
0BCBH-0BCDH
Go complement the value in register pair HL
0BCEH
LD A,C
Load Register A with zero
0BCFH
SBC A,B
Adjust the value of the sign test
0BD0H-0BD1H
Jump to 0BD5H

0BD2H-0BF1H – INTEGER ADDITION
“ADDINT”

  • Integer addition (REG 1=DE+HL). After execution NTF=2, or 4 if overflow has occurred, in which case the result in REG 1 will be single-precision. The result is returned in both REG 1 and the HL register pair.
  • Adds the integer value in DE to the integer in HL. The sum is left in HL and the orginal contents of DE are preserved. If overflow occurs (sum exceeds 2**15), both values are converted to single precision and then added. The result would be left in Reg 1 and the mode flag would be updated.
  • Note: If you wanted to add 2 integers via a ROM call, store one input into DE and the other into HL, and then call 0BD2H. The result will be in 4121H-4122H and in HL, with a 2 in 40AFH, and will take about 130 microseconds. If there is an overflow, the result will be converted to Single Precision and put into 4121H-4124H (with a 4 in 40AFH).
0BD2H
LD A,H
Load Register A with the MSB of the integer value in register pair HL
0BD3H
RLA
Put the value of the sign bit into the Carry flag
0BD4H
SBC A,A
Adjust Register A according to the value of the sign bit
0BD5H
LD B,A
Load Register B with the result of the sign test
0BD6H
PUSH HL
Save the integer value in register pair HL on the stack
0BD7H
LD A,D
Load Register A with the MSB of the integer value in register pair DE
0BD8H
RLA
Put the value of the sign bit into the Carry flag
0BD9H
SBC A,A
Adjust Register A according to the value of the sign bit
0BDAH
ADD HL,DE
Add the integer value in register pair DE to the integer value in register pair HL
0BDBH
ADC A,B
Add the Carry flag and the value from the sign test for the integer value in register pair HL in Register B to the value of the sign test for the integer value in register pair DE in Register A
0BDCH
RRCA
Put the value of the Carry flag in Register A
0BDDH
XOR H
Combine the value of the sign bit for the result in register H with the value in Register A
0BDEH-0BE0H
Jump unless overflow has occurred
0BE1H
PUSH BC
Save the value of the sign test in Register B on the stack
0BE2H
EX DE,HL
Load register pair HL with the integer value in register pair DE
0BE3H-0BE5H
Go convert the register value in register pair HL to single precision and return with the result in REG 1
0BE6H
POP AF
Get the value of the sign test from the stack and put it in Register A
0BE7H
POP HL
Get the integer value from the stack and put it in register pair HL
0BE8H-0BEAH
Call 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order)
0BEBH
EX DE,HL
Load register pair DE with the integer value in register pair HL
0BECH-0BEEH
Go convert the integer value in register pair DE to single precision and return with the result in REG 1
0BEFH-0BF1H
Go perform single precision addition

0BF2H-0ClEH – INTEGER MULTIPLICATION
“MLTINT”

  • Integer multiply. (REG 1=DE*HL). Multiplies HL by DE. The product is left in HL and DE is preserved. If overflow occurs, both values are converted to single precision and the operation is restarted. The product would be left in REG 1.
  • Note: If you wanted to multiply two integers, store one input in DE, the other in HL CALL 0BF2H. The result is in 4121H-4122H and in HL, with a 2 in 40AFH (but in an overflow the result is converted to single precision format and stored in 4121H-4124H, with a 4 in 40AFH. Process takes approximately 900 microseconds.
0BF2H
“IMUL”
LD A,H
Load Register A with the MSB of the integer value in register H
0BF3H
OR L
Combine the LSB of the integer value in register L with the MSB of the integer value in Register A
0BF4H-0BF6H
Jump if the integer value in register pair HL is equal to zero
0BF7H
PUSH HL
Save the integer value in register pair HL on the stack
0BF8H
PUSH DE
Save the integer value in register pair DE on the stack
0BF9H-0BFBH
Go convert any negative integer values to positive and return with Register B set according to the value of the sign bits
0BFCH
PUSH BC
Save the value of the sign bit test in Register B on the stack
0BFDH
LD B,H
Load Register B with the MSB of the integer value in register H
0BFEH
LD C,L
Load register C with the LSB of the integer value in register L
0BFFH-0C01H
LD HL,0000H
Load register pair HL with zero
0C02H-0C03H
LD A,10H
Load Register A with the counter value (which is 16)
0C04H
ADD HL,HL
Multiply the result in register pair HL by two
0C05H-0C06H
Jump if the result in register pair HL has overflowed
0C07H
EX DE,HL
Exchange the integer value in register pair DE with the integer result in register pair HL
0C08H
ADD HL,HL
Multiply the integer value in register pair HL by two
0C09H
EX DE,HL
Exchange the integer result in register pair DE with the integer value in register pair HL
0C0AH-0C0BH
Jump if the most significant bit of the integer register pair DE wasn’t set
0C0CH
ADD HL,BC
Add the integer value in register pair BC to the integer result in register pair HL
0C0DH-0C0FH
Jump if the result in register pair HL has overflowed
0C10H
DEC A
Decrement the value of the counter in Register A
0C11H-0C12H
Loop until the multiplication has been completed
0C13H
POP BC
Get the value of the sign test from the stack and put it in Register B
0C14H
POP DE
Get the integer value from the stack and put it in register pair DE
0C15H
LD A,H
Load Register A with the MSB of the result in register H
0C16H
OR A
Check to see if the sign bit in the MSB of the integer result in Register A is set
0C17H-0C19H
Jump if the integer result in register pair HL is negative
0C1AH
POP DE
Get the integer value from the stack and put it in register pair DE
0C1BH
LD A,B
Load Register A with the value of the sign test in Register B
0C1CH-0C1EH
Jump to 0C4DH

0ClFH-0C34H – LEVEL II BASIC MATH ROUTINE

0C1FH-0C20H
XOR 80H
Clear the sign bit for the MSB of the integer value in Register A which is 1000 0000
0C21H
OR L
Combine the value of the LSB for the integer value in register L with the adjusted MSB of the integer value in Register A
0C22H-0C23H
Jump if the result is equal to zero
0C24H
EX DE,HL
Load register pair HL with the integer value in register pair DE
0C25H-0C28H
LD BC,E1C1H
Z-80 Trick – See the note at 0134H for an explanation
0C26H
POP BC
Get the value of the sign test from the stack and put it in Register B
0C27H
POP HL
Get the integer value from the stack and put it in register pair HL
0C28H-0C2AH
Go convert the integer value in register pair HL to single precision and return with the result in REG 1
0C2BH
POP HL
Get the integer value from the stack and put it in register pair HL
0C2CH-0C2EH
Call 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order)
0C2FH-0C31H
Go convert the integer value in register pair HL to single precision and return with the result in REG 1
0C32H
POP BC
Get the exponent and the MSB of the single precision value from the stack and put it in register pair BC
0C33H
POP DE
Get the NMSB and the LSB of the single precision value from the stack and put it in register pair DE
0C34H-0C36H
Jump to the SINGLE PRECISION MULTIPLY routine at 0847H (which multiplies the current value in REG 1 by the value in (BC/DE). The product is left in REG 1

0C37H-0C44H – LEVEL II BASIC MATH ROUTINE

0C37H
LD A,B
Load Register A with the result of the sign test in Register B
0C38H
OR A
Check to see if the result is supposed to be negative
0C39H
POP BC
Get the value from the stack and put it in register pair BC
0C3AH-0CJCH
Jump if the result is supposed to be negative
0C3DH
PUSH DE
Save the integer value in register pair DE on the stack
0C3EH-0C40H
Go convert the integer result in register pair HL to single precision and return with the result in REG 1
0C41H
POP DE
Get the integer value from the stack and put it in register pair DE
0C42H-0C44H
Jump to 0982H

0C45H-0C5AH – LEVEL II BASIC MATH ROUTINE

0C45H
LD A,H
Load Register A with the MSB of the integer value in register H
0c46H
XOR D
Combine the MSB of the integer value in register D with the MSB of the integer value in Register A
0C47H
LD B,A
Save the result of the combined signs in Register A into Register B
0C48H-0C4AH
Go convert a negative integer value in register pair HL to positive
0C4BH
EX DE,HL
Exchange the integer value in register pair DE with the integer value in register pair HL
0C4CH
LD A,H
Load Register A with the MSB of the integer value in register H
0C4DH
OR A
Check the value of the sign for the MSB of the integer value in Register A
0C4EH-0C50H
Jump if the integer value in register pair HL is positive
0C51H
XOR A
Zero Register A.
Negate HL routine. This routine changes the sign of the HL register pair and stores it in the ACC. (HL=REG 1=-HL) The result is returned in both the HL register pair and the ACC
0C52H
LD C,A
Load register C with the value in Register A
0C53H
SUB L
Subtract the LSB of the integer value in register L from the value in Register A
0C54H
LD L,A
Save the adjusted value in Register A in register L
0C55H
LD A,C
Load Register A with the value in register C
0C56H
SBC A,H
Subtract the MSB of the integer value in register H from the value in Register A
0C57H
LD H,A
Save the adjusted value in Register A into register H
0C58H-0C5AH
Jump to 0A9AH

0C5BH-0C6FH – LEVEL II BASIC MATH ROUTINE

0C5BH-0C5DH
LD HL,(4121H)
Load register pair HL with the integer value in REG 1
0C5EH-0C60H
Go convert the integer value in register pair HL to positive if it’s negative
0C61H
LD A,H
Load Register A with the MSB of the integer value in register H
0C62H-0C63H
XOR 80H
Invert the value of the sign bit in Register A which is 1000 0000
0C64H
OR L
Combine the LSB of the integer value in register L with the adjusted MSB of the integer value in Register A
0C65H
RET NZ
Return if the integer value in REG 1 isn’t equal to -32768
0C66H
EX DE,HL
Load register pair DE with the integer value in register pair HL
0C67H-0C69H
Go set the number type flag to single precision
0C6AH
XOR A
Zero Register A
0C6BH-0C6CH
LD B,98H
Load Register B with an exponent
0C6DH-0C6FH
Jump to 0969H

0C70H-0C76H – DOUBLE PRECISION SUBTRACTION
“SUBDP”

  • Double-precision subtraction (REG 1=ACC-AACC).
    Subtracts the double precision value in REG 2 from the value in REG 1. The difference is left in REG 1.
  • Note: If you wanted to subtract two double precision numbers, store the minuend in 411DH-4124H and the subtrahend in 4127H-412EH, and CALL 0C70H. The result (in double precision format) is in 411DH-4124H in approximately 1.3 milliseconds.
0C70H-0C72H
“DSUB”
LD HL,412DH
Load register pair HL with the address of the MSB in REG 2
0C73H
LD A,(HL)
Load Register A with the MSB of the double precision value in REG 2 at the location of the memory pointer in register pair HL
0C74H-0C75H
XOR 80H
Invert the value of the sign bit for the MSB of the double precision value in Register A which is 1000 0000
0C76H
LD (HL),A
Save the adjusted MSB of the double precision value in Register A in REG 2 at the location of the memory pointer in register pair HL

0C77H-0CCEH -DOUBLE PRECISION ADDITION
“ADDDP”

  • Double-precision addition (REG 1=ACC+AACC).
    Adds the double precision value in REG 2 to the value in REG 1. Sum is left in REG 1.
  • Note: If you wanted to add 2 double precision numbers via a ROM call, store one input into 411DH-4124H and the other in 4127H-412EH. Then call 0C77H. The double precision result will be stored in 411DH-4124H approximately 1.3 milliseconds later.
0C77H-0C79H
“DADD”
LD HL,412EH
Load register pair HL with the address of the exponent in REG 2
0C7AH
LD A,(HL)
Load Register A with the exponent of the double precision value in REG 2 at the location of the memory pointer in register pair HL
0C7BH
OR A
Check to see if the double precision value in REG 2 is equal to zero
0C7CH
RET Z
Return if the double precision value in REG 2 is equal to zero
0C7DH
LD B,A
Load Register B with the value of the exponent for the double precision value in Register A
0C7EH
DEC HL
Decrement the value of the memory pointer in register pair HL
0C7FH
LD C,(HL)
Load register C with the value of the MSB of the double precision value in REG 2 at the location of the memory pointer in register pair HL
0C80H-0C82H
LD DE,4124H
Load register pair DE with the address of the exponent in REG 1
0C83H
LD A,(DE)
Load Register A with the value of the exponent of the double precision value in REG 1 at the location of the memory pointer in register pair DE
0C84H
OR A
Check to see if the double precision value in REG 1 is equal to zero
0C85H-0C87H
Jump if the double precision value in REG 1 is equal to zero
0C88H
SUB B
Subtract the value of the exponent for the double precision value in REG 2 in Register B from the value of the exponent for the double precision value in REG 1 in Register A
0C89H-0C8AH
Jump if the double precision value in REG 1 is greater than or equal to the double precision value in REG 2
0C8BH
CPL
Complement the difference between the two exponents in Register A
0C8CH
INC A
Increment the value of the difference for the exponents in Register A so that Register A will hold the positive difference
0C8DH
PUSH AF
Save the difference for the exponents in Register A on the stack
0C8EH-0C8FH
LD C,08H
Load register C with the counter value which is 8
0C90H
INC HL
Increment the value of the memory pointer in register pair HL so that it will be pointing to the exponent of the double precision value in REG 2
0C91H
PUSH HL
Save the value of the memory pointer in register pair HL on the stack
0C92H
LD A,(DE)
Load Register A with the value at the location of the memory pointer in register pair DE
0C93H
LD B,(HL)
Load Register B with the value at the location of the memory pointer in register pair HL
0C94H
LD (HL),A
Save the value in Register A at the location of the memory pointer in register pair HL
0C95H
LD A,B
Load Register A with the value in Register B
0C96H
LD (DE),A
Save the value in Register A at the location of the memory pointer in register pair DE
0C97H
DEC DE
Decrement the value of the memory pointer in register pair DE
0C98H
DEC HL
Decrement the value of the memory pointer in register pair HL
0C99H
DEC C
Decrement the value of the counter in register C
0C9AH-0C9BH
Loop until the double precision values in REG 1 and REG 2 have been exchanged
0C9CH
POP HL
Get the value of the memory pointer from the stack and put it in register pair HL
0C9DH
LD B,(HL)
Load Register B with the value of the exponent for the double precision value in REG 2 at the location of the memory pointer in register pair HL
0C9EH
DEC HL
Decrement the value of the memory pointer in register pair HL
0C9FH
LD C,(HL)
Load register C with the value of the MSB for the double precision value in REG 2 at the location of the memory pointer in register pair HL
0CA0H
POP AF
Get the difference for the exponents from the stack and put it in Register A
0CA1H-0CA2H
CP 39H
Check to see if the difference between the two exponents is greater than 56 bits
0CA3H
RET NC
Return if the difference between the two exponents is greater than 56 bits
0CA4H
PUSH AF
Save the difference for the exponents in Register A on the stack
0CA5H-0CA7H
Go turn on the sign bits for the double precision numbers
0CA8H
INC HL
Increment the value of the memory pointer in register pair HL
0CA9H-0CAAH
LD (HL),00H
Zero the location of the memory pointer in register pair HL
0CABH
LD B,A
Save the result of the sign test in Register A in Register B
0CACH
POP AF
Get the difference for the exponents from the stack and put it in Register A
0CADH-0CAFH
LD HL,412DH
Load register pair HL with the address of the MSB in REG 2
0CB0H-0CB2H
Go shift the double precision value in REG 2 until it lines up with the double precision value in REG 1
0CB3H-0CB5H
LD A,(4126H)
Get the bits shifted out of the double precision value in REG2 and put it in Register A
0CB6H-0CB8H
LD (411CH),A
Save the value in Register A.
Note: 411CH holds Used by floating point routines
0CB9H
LD A,B
Load Register A with the value of the sign test in Register B
0CBAH
OR A
Check to see if the signs are equal
0CBBH-0CBDH
Go subtract the values if the signs aren’t equal
0CBEH-0CC0H
Go add the values
0CC1H-0CC3H
Jump if the Carry flag isn’t set
0CC4H
EX DE,HL
Load register pair HL with the value of the memory pointer in register pair DE
0CC5H
INC (HL)
Increment the value of the exponent at the location of the memory pointer in register pair HL
0CC6H-0CC8H
Display an ?OV ERROR if the exponent for the double precision result in REG 1 is too large
0CC9H-0CCBH
Go adjust the double precision result in REG 1
0CCCH-0CCEH
Jump to 0D0EH

0CCFH-0DlFH – DOUBLE PRECISION MATH ROUTINE

0CCFH-0CD1H
Go subtract the double precision values
0CD2H-0CD4H
LD HL,4125H
Load register pair HL with the address of the sign for the result.
Note: 4125H-4126H is used by floating point routines
0CD5H-0CD7H
Go complement the result in REG 1 if the Carry flag is set
0CD8H
XOR A
Zero Register A
0CD9H
LD B,A
Load Register B with the value in Register A
0CDAH-0CDCH
LD A,(4123H)
Load Register A with the value of the MSB of the double precision result in REG 1
0CDDH
OR A
Check to see if the MSB of the double precision result is equal to zero
0CDEH-0CDFH
Jump forward to 0CFEH if the MSB of the double precision value is nonzero
0CE0H-0CE2H
LD HL,411CH
Load register pair HL with the starting address of REG 1 minus one.
Note: 411CH holds Used by floating point routines
0CE3H-0CE4H
LD C,08H
Load register C with the number of bytes to be shifted
0CE5H
LD D,(HL)
Load register D with the value at the location of the memory pointer in register pair HL
0CE6H
LD (HL),A
Save the value in Register A at the location of the memory pointer in register pair HL
0CE7H
LD A,D
Load Register A with the value in register D
0CE8H
INC HL
Increment the value of the memory pointer in registerpair HL
0CE9H
DEC C
Decrement the number of bytes to be shifted in register C
0CEAH-0CEBH
Loop until all of the bytes in the double precision value have been shifted
0CECH
LD A,B
Load Register A with the number of bits shifted in Register B
0CEDH-0CEEH
SUB 08H
Subtract the number of bits just shifted from the shift counter in Register A
0CEFH-0CF0H
CP C0H
Check to see if the whole of the double precision value has been shifted
0CF1H-0CF2
H Jump if the whole of the double precision value hasn’t been shifted
0CF3H-0CF5H
Go make the double precision value equal to zero if the whole of the double precision value has been shifted
0CF6H
DEC B
Decrement the shift counter in Register B
0CF7H-0CF9H
LD HL,411CH
Load register pair HL with the starting address of REG 1 minus one.
Note: 411CH holds Used by floating point routines
0CFAH-0CFCH
Gosub to shift the double precision value in REG 1 once
0CFDH
OR A
Check to see if the sign bit of the MSB of the double precision value in Register A is set
0CFEH-0D00H
Loop until the sign bit is set
0D01H
LD A,B
Load Register A with the value of the shift counter in Register B
0D02H
OR A
Check to see if the shift counter in Register A is equal to zero
0D03H-0D04H
Jump if the value in REG 1 wasn’t shifted at all
0D05H-0D07H
LD HL,4124H
Load register pair HL with the address of the exponent in REG 1
0D08H
ADD A,(HL)
Add the value of the exponent for the double preci�sion value in REG 1 at the location of the memory pointer in register pair HL to the value of the shift counter in Register A
0D09H
LD (HL),A
Save the adjusted exponent for the double precision value in Register A at the location of the memory pointer in register pair HL
0D0AH-0D0CH
Jump if overflow didn’t occur
0D0DH
RET Z
Return if the double precision value is equal to zero
0D0EH-0D10H
LD A,(411CH)
Load Register A with the value of the rounding byte at the location of the starting address of REG 1 minus one.
Note: 411CH holds Used by floating point routines
0D11H
OR A
Check to see if there is a bit to be shifted into the double precision value in REG 1
0D12H-0D14H
Go move the bit into the double precision value if necessary
0D15H-0D17H
LD HL,4125H
Load register pair HL with the address of the sign for the result.
Note: 4125H-4126H is used by floating point routines
0D18H
LD A,(HL)
Load Register A with the value of the sign for the result at the location of the memory pointer in register pair HL
0D19H-0D1AH
AND 80H
Mask the value of the sign for the result in Register A which is 1000 0000
0D1BH
DEC HL
Decrement the value of the memory pointer in register pair HL so that it points to the exponent in REG 1
0D1CH
DEC HL
Decrement the value of the memory pointer in register pair HL so that it points to the MSB inREG 1
0D1DH
XOR (HL)
Combine the value of the MSB of the double preci�sion value in REG 1 at the location of the memory pointer in register pair HL with the value of the sign for the result in Register A
0D1EH
LD (HL),A
Save the adjusted MSB of the double precision value in Register A at the location of the memory pointer in register pair HL
0D1FH
RET
Return

0D20H-0D32H – DOUBLE PRECISION MATH ROUTINE

0D20H-0D22H
LD HL,411DH
Load register pair HL with the starting address in REG 1.
Note: 411DH-4124H holds REG 1
0D23H-0D24H
LD B,07H
Load Register B with the number of bytes to be bumped for the double precision value in REG 1
0D25H
INC (HL)
Increment the value at the location of the memory pointer in register pair HL
0D26H
RET NZ
Return if the value at the location of the memory pointer in register pair HL isn’t equal to zero
0D27H
INC HL
Increment the value of the memory pointer in register pair HL
0D28H
DEC B
Decrement the value of the byte counter in Register B
0D29H-0D2AH
Loop until all of the necessary bytes have been bumped
0D2BH
INC (HL)
Increment the value of the exponent at the location of the memory pointer in register pair HL
0D2CH-0D2EH
Go to the Level II BASIC error routine and display an OV ERROR message if the exponent for the double precision value in REG 1 is too large
0D2FH
DEC HL
Decrement the value of the memory pointer in register pair HL
0D30H-0D31H
LD (HL),80H
Save a new MSB at the location of the memory pointer in register pair HL
0D32H
RET
Return

0D33H-0D44H – DOUBLE PRECISION MATH ROUTINE

0D33H-0D35H
LD HL,4127H
Load register pair HL with the starting address of REG 2.
Note: 4127H-412EH holds REG 2
0D36H-0D38H
LD DE,411DH
Load register pair DE with the starting address of REG 1.
Note: 411DH-4124H holds REG 1
0D39H-0D3AH
LD C,07H
Load register C with the number of bytes to be added
0D3BH
XOR A
Clear the Carry flag
0D3CH
LD A,(DE)
Load Register A with the value in REG 1 at the location of the memory pointer in register pair DE
0D3DH
ADC A,(HL)
Add the value in REG 2 at the location of the memory value in Register A
0D3EH
LD (DE),A
Save the result in Register A in REGI at the location of the memory pointer in register pair DE
0D3FH
INC DE
Increment the value of the memory pointer in register pair DE
0D40H
INC HL
Increment the value of the memory pointer in register pair HL
0D41H
DEC C
Decrement the number of bytes to be added in register C
0D42H-0D43H
Loop until all of the bytes for the double precision values have been added
0D44H
RET
Return

0D45H-0D56H – DOUBLE PRECISION MATH ROUTINE

0D45H-0D47H
LD HL,4127H
Load register pair HL with the starting address of REG 2.
Note: 4127H-412EH holds REG 2
0D48H-0D4AH
LD DE,411DH
Load register pair DE with the starting address of REG 1.
Note: 411DH-4124H holds REG 1
0D4BH-0D4CH
LD C,07H
Load register C with the number of bytes to be subtracted
0D4DH
XOR A
Clear the Carry flag
0D4EH
LD A,(DE)
Load Register A with the value in REGI at the loca�tion of the memory pointer in register pair DE
0D4FH
SBC A,(HL)
Subtract the value in REG 2 at the location of the memory pointer in register pair HL from the value in Register A
0D50H
LD (DE),A
Save the result in Register A in REG 1 at the location of the memory pointer in register pair DE
0D51H
INC DE
Increment the value of the memory pointer in register pair DE
0D52H
INC HL
Increment the value of the memory pointer in register pair HL
0D53H
DEC C
Decrement the number of bytes to be subtracted for the double precision values in register C
0D54H-0D55H
Loop until all of the bytes for the double precision values have been subtracted
0D56H
RET
Return

0D57H-0D68H – DOUBLE PRECISION MATH ROUTINE

0D57H
LD A,(HL)
Load Register A with the value of the sign at the location of the memory pointer in register pair HL
0D58H
CPL
Complement the value of the sign in Register A
0D59H
LD (HL),A
Save the value of the sign in Register A at the location of the memory pointer in register pair HL
0D5AH-0D5CH
LD HL,411CH
Load register pair HL with the starting address of REG 1 minus one.
Note: 411CH holds Used by floating point routines
0D5DH-0D5EH
LD B,08H
Load Register B with the number of bytes to be reversed
0D5FH
XOR A
Zero Register A
0D60H
LD C,A
Load register C with the value in Register A
0D61H
LD A,C
Load Register A with the value in register C
0D62H
SBC A,(HL)
Subtract the value at the location of the memory pointer in register pair HL from the value in Register A
0D63H
LD (HL),A
Save the reversed value in Register A at the location of the memory pointer in register pair HL
0D64H
INC HL
Increment the value of the memory pointer in register pair HL
0D65H
DEC B
Decrement the number of bytes to be reversed in Register B
0D66H-0D67H
Loop until all of the bytes for the double precision number in REG 1 have been reversed
0D68H
RET
Return

0D69H-0D8FH – DOUBLE PRECISION MATH ROUTINE

0D69H
LD (HL),C
Save the MSB of the double precision value in register C at the location of the memory pointer in register pair HL
0D6AH
PUSH HL
Save the value of the memory pointer in register pair HL on the stack
0D6BH-0D6CH
SUB 08H
Subtract 8 from the number of bits to be shifted from the number of bits to be shifted in Register A
0D6DH-0D6EH
Jump if there are less than 8 bits to be shifted
0D6FH
POP HL
Get the value of the memory pointer from the stack and put it in register pair HL
0D70H
PUSH HL
Save the value of the memory pointer in register pair HL on the stack
0D71H-0D73H
LD DE,0800H
Load register pair DE with the number of bytes to be shifted (which is 2048) and the value to be shifted into the double precision value
0D74H
LD C,(HL)
Load register C with the value at the location of the memory pointer in register pair HL
0D75H
LD (HL),E
Save the value in register E at the location of the memory pointer in register pair HL
0D76H
LD E,C
Load register E with the value in register C
0D77H
DEC HL
Decrement the value of the memory pointer in register pair HL
0D78H
DEC D
Decrement the number of bytes shifted in register D
0D79H-0D7AH
Loop until all of the bytes have been shifted
0D7BH-0D7CH
Loop until there are less than 8 bits to be shifted
0D7DH-0D7EH
ADD 09H
Adjust the number of bits to be shifted in Register A so that it holds the correct value (adjustment against 0000 1001)
0D7FH
LD D,A
Load register D with the number of bits to be shifted in Register A
0D80H
XOR A
Zero Register A
0D81H
POP HL
Get the value of the memory pointer from the stack and put it in register pair HL
0D82H
DEC D
Decrement the number of bits to be shifted in register D
0D83H
RET Z
Return if all of the bits have been shifted
0D84H
PUSH HL
Save the value of the memory pointer in register pair HL on the stack
0D85H-0D86H
LD E,08H
Load register E with the number of bytes to be shifted
0D87H
LD A,(HL)
Load Register A with the value at the location of the memory pointer in register pair HL
0D88H
RRA
Shift the value in Register A
0D89H
LD (HL),A
Save the adjusted value in Register A at the location of the memory pointer in register pair HL
0D8AH
DEC HL
Decrement the value of the memory pointer in register pair HL
0D8BH
DEC E
Decrement the number of bytes to be shifted in register E
0D8CH-0D8DH
Loop until all of the bytes have been shifted
0D8EH-0D8FH
Loop until all of the bits have been shifted

0D90H-0D96H – DOUBLE PRECISION MATH ROUTINE

0D90H-0D92H
LD HL,4123H
Load register pair HL with the address of the MSB of the double precision value in REG 1
0D93H-0D94H
LD D,01H
Load register D with the number of bits to be shifted
0D95H-0D96H
Jump to 0D84H

0D97H-0DA0H – DOUBLE PRECISION MATH ROUTINE

0D97H-0D98H
LD C,08H
Load register C with the number of bytes to be shifted
0D99H
LD A,(HL)
Load Register A with the value at the location of the memory pointer in register pair HL
0D9AH
RLA
Shift the value in Register A
0D9BH
LD (HL),A
Save the shifted value in Register A at the location of the memory pointer in register pair HL
0D9CH
INC HL
Increment the value of the memory pointer in register pair HL
0D9DH
DEC C
Decrement the byte counter in register C
0D9EH-0D9FH
Loop until all of the bytes have been shifted
0DA0H
RET
Return

0DAlH-0DD3H – DOUBLE PRECISION MULTIPLICATION
“MLTDP”

  • Double-precision multiplication (REG 1=ACC*AACC).
    Multiplies the double precision value in REG 1 by the value in REG 2. The product is left in REG 1.
  • Note: If you wanted to multiply two double precision numbers store one operand in 411DH-4124H, and store the other in 4127H-412EH and then CALL 0DA1H. The result (in double precision format) is in 411DH-4124H in approximately 22 milliseconds.
0DA1H-0DA3H
“DMUL”
Go check to see if the value in REG 1 is equal to zero
0DA4H
RET Z
Return if the double precision value in REG 1 is equal to zero
0DA5H-0DA7H
Go figure the new exponent
0DA8H-0DAAH
Go move the double precision value in REG 1 to a temporary work area
0DABH
LD (HL),C
Zero the location at the current value of the memory pointer in register pair HL
0DACH
INC DE
Increment register pair DE so that it points to the LSB of the double precision value in the temporary work area
0DADH-0DAEH
LD B,07H
Load Register B with the number of bytes to be figured
0DAFH
LD A,(DE)
Load Register A with the value at the location of the memory pointer in register pair DE
0DB0H
INC DE
Increment the value of the memory pointer in register pair DE
0DB1H
OR A
Check to see if the value in Register A is equal to zero

0DB2H – INTEGER ADD routine

Adds the integer value in DE to the integer in HL. The sum is left in HL and the orginal contents of DE are preserved. If overflow occurs (sum exceeds 2**15), both values are converted to single precision and then added. The result would be left in REG 1 and the mode flag would be updated.

0DB2H
“IADD”
PUSH DE
Save the value of the memory pointer in register pair DE on the stack
0DB3H-0DB4H
Jump if the value in Register A is equal to zero
0DB5H-0DB6H
LD C,08H
Load register C with the numberofbits to be shifted
0DB7H
PUSH BC
Save the value in register pair BC on the stack
0DB8H
RRA
Shift the value in Register A one place to the right
0DB9H
LD B,A
Load Register B with the value in Register A
0DBAH-0DBCH
Go add the value in REG 2 to the total in REG 1 if bit zero of Register A was set
0DBDH-0DBFH
Go shift the value of the total in REG 1
0DC0H
LD A,B
Load Register A with the adjusted value in Register B
0DC1H
POP BC
Get the value from the stack and put it in register pair BC
0DC2H
DEC C
Decrement the number of bits to be shifted in regis�ter C
0DC3H-0DC4H
Loop back to 0DB7H until all of the bits have been shifted
0DC5H
POP DE
Get the value from the stack and put it in register pair DE
0DC6H
DEC B
Decrement the number of bytes to be figured in Register B
0DC7H-0DC8H
Loop back to 0DAFH until all of the bytes have been figured
0DC9H-0DCBH
Jump to 0CD8H
0DCCH-0DCEH
LD HL,4123H
Load register pair HL with the address of the MSB in REG 1
0DCFH-0DD1H
Go shift the double precision total in REG 1
0DD2H-0DD3H
Jump to 0DC5H

0DD4H-0DDBH – DOUBLE PRECISION CONSTANT STORAGE AREA

0DD4H-0DDBH
00 00 00 00 00 00 20 84
A double precision constant equal to 10.0 is stored here

0DDCH-0DE4H – DOUBLE PRECISION MATH ROUTINE

0DDCH-0DDEH
LD DE,0DD4H
Load register pair DE with the starting address of the double precision constant stored above
0DDFH-0DE1H
LD HL,4127H
Load register pair HL w1 th the starting address of REG 2.
Note: 4127H-412EH holds REG 2
0DE2H-0DE4H
Go move the double precision constant into REG 2

0DE5H-0E38H – DOUBLE PRECISION DIVISION
“DIVDP”

  • Double-precision division (REG 1=ACC / AACC).
    Divides the double precision value in WRAl by the value in REG 2. The quotient is left in REG 1.
  • To use a ROM call to divide two double precision numbers, store the dividend in 411DH-4124H, and the divisor in 4127H-412EH and then CALL 0DE5H. The result (in double precision format) is in 411DH-4124H and then pproximately 42 milliseconds. Overflow or /0 will error out and return to Level II.
0DE5H-0DE7H
“DDIV”
LD A,(412EH)
Load Register A with the value of the exponent for the double precision value in REG 2
0DE8H
OR A
Check to see if the double precision value in REG 2 is equal to zero
0DE9H-0DEBH
Display a /0 ERROR message if the double precision value in REG 2 is equal to zero
0DECH-0DEEH
Go figure the value of the new exponent
0DEFH
INC (HL)
Increment the value of the exponent in REG 1
0DF0H
INC (HL)
Increment the value of the exponent in REG 1
0DF1H-0DF3H
Go move the double precision value from REG 1 into the temporary work area
0DF4H-0DF6H
LD HL,4151H
Load register pair HL with the address of the expo�nent in the temporary work area
0DF7H
LD (HL),C
Zero the value of the exponent in the temporary work area at the location of the memory pointer in register pair HL
0DF8H
LD B,C
Zero Register B
0DF9H-0DFBH
LD DE,414AH
Load register pair DE with the starting address of the double precision value in the temporary work area.
Note: 414AH-4151H holds Used by floating pointer routines
0DFCH-0DFEH
LD HL,4127H
Load register pair HL with the starting address of the double precision value in REG 2.
Note: 4127H-412EH holds REG 2
0DFFH-0E01H
Go subtract the double precision value in REG 2 from the double precision value in the temporary work area
0E02H
LD A,(DE)
Load Register A with the value at the location of the memory pointer in register pair DE
0E03H
SBC A,C
Subtract the value in register C from the value in Register A
0E04H
CCF
Complement the value of the Carry flag
0E05H-0E06H
Jump if the double precision value in REG 2 is greater than the double precision value in the temporary work area
0E07H-0E09H
LD DE,414AH
Load register pair DE with the starting address of the double precision value in the temporary work area.
Note: 414AH-4151H holds Used by floating pointer routines
0E0AH-0E0CH
LD HL,4127H
Load register pair HL with the starting address of tht double precision value in REG 2.
Note: 4127H-412EH holds REG 2
0E0DH-0E0FH
Go add the double precision value in REG 2 to the double precision value in the temporary work area
0E10H
XOR A
Zero Register A
0E12H
Save the value of the exponent in Register A at the location of the memory pointer in register pair DE
0E13H
LD A,(4123H)
Increment the counter in Register B
0E14H-0E16H
INC A
Load Register A with the value of the MSB of the total in REG 1
0E17H
DEC A
Increment the value of the MSB for the double precision result in Register A
0E18H
RRA
Decrement the value of the MSB for the double precision result in Register A
0E19H
Put the value of the Carry flag into Register A as the sign bit
0E1AH-0E1CH
RLA
Jump if the sign bit was set. 0ElDH Put the sign bit in Register A back into the Carry flag
0E1EH-0E20H
LD HL,411DH
Load register pair HL with the starting address of the double precision result in REG 1.
Note: 411DH-4124H holds REG 1
0E21H-0E22H
LD C,07H
Load register C with the number of bytes to be shifted
0E23H-0E25H
Go shift the double precision result in REG 1
0E26H-0E28H
LD HL,414AH
Load register pair HL with the starting address of the double precision value in the temporary work area.
Note: 414AH-4151H holds Used by floating pointer routines
0E29R-0E2BH
Go shift the double precision value in the temporary work area
0E2CH
LD A,B
Load Register A with the value of the counter in Register B
0E2DH
OR A
Check to see if the value of the counter in Register A is equal to zero
0E2EH-0E2FH
Loop until done if the value of the counter in Register A isn’t equal to zero
0E30H-0E32H
LD HL,4124H
Load register pair HL with the address of the exponent for the double precision result in REG 1 (which is 16676)
0E33H
DEC (HL)
Decrement the value of the exponent for the double precision result in REG 1 at the location of the mem�ory pointer in register pair HL
0E34H-0E35H
Loop until done if overflow didn’t occur
0E36H-0E38H
Display an ?OV ERROR if the exponent for the result in REG 1 is too small

0E39H-0E4CH – DOUBLE PRECISION MATH ROUTINE

0E39H
LD A,C
Load Register A with the MSB of the double precision value in REG 2 in register C
0E3AH-0E3CH
LD (412DH),A
Save the MSB of the double precision value in REG 2 in Register A
0E3DH
DEC HL
Decrement the value of the memory pointer in register pair HL
0E3EH-0E40H
LD DE,4150H
Load register pair DE with the starting address of the temporary work area
0E41H-0E43H
LD BC,0700H
Load Register B with the number of bytes to be moved (which is 1792) and zero register C
0E44H
LD A,(HL)
Load Register A with the value at the location of the memory pointer in register pair HL
0E45H
LD (DE),A
Save the value in Register A at the location of the memory pointer in register pair DE
0E46H
LD (HL),C
Zero the location of the memory pointer in register pair HL
0E47H
DEC DE
Decrement the value of the memory pointer in register pair DE
0E48H
DEC HL
Decrement the value of the memory pointer in register pair HL
0E49H
DEC B
Decrement the value of the byte counter in Register B
0E4AH-0E4BH
Loop until the double precision value has been moved to the temporary work area
0E4CH
RET
Return

0E4DH-0E64H – LEVEL II BASIC MATH ROUTINE

  • This routine multiplies the current double-precision value by 2 by adding it to itself. First the current value is moved to a saved location, and then DP add routine adds the current value to that saved value.
0E4DH-0E4FH
Go move the value in REG 1 to REG 2
0E50H
EX DE,HL
Load register pair HL with the value of the memory pointer in register pair DE
0E51H
DEC HL
Decrement the value of the memory pointer in register pair HL
0E52H
LD A,(HL)
Load Register A with the value of the exponent in REG 1 at the location of the memory pointer in register pair HL
0E53H
OR A
Check to see if the value in REG 1 is equal to zero
0E54H
RET Z
Return if the value in REG 1 is equal to zero
0E55H-0E56H
ADD 02H
Adjust the exponent for the following addition
0E57H-0E59H
Display an ?OV ERROR if the adjusted exponent in Register A is too large
0E5AH
LD (HL),A
Save the adjusted exponent in Register A in REG 1 at the location of the memory pointer in register pair HL
0E5BH
PUSH HL
Save the value of the memory pointer in register pair HL on the stack
0E5CH-0E5EH
Call the DOUBLE PRECISION ADD function (whcih adds the double precision value in REG 2 to the value in REG 1. Result is left in REG 1)
0E5FH
POP HL
Get the value of the memory pointer from the stack and put it in register pair HL
0E60H
INC (HL)
Increment the value of the exponent for the double preci�sion value in REG 1 at the location of the memory pointer in register pair HL
0E61H
RET NZ
Return if overflow didn’t occur
0E62H-0E64H
Display an ?OV ERROR if the exponent in REG 1 at the location of the memory pointer in register pair HL is too large

0E65H-0F88H – ASCII TO DOUBLE PRECISION

  • This routine converts an ASCII string (pointed to by HL) to a double-precision value and stores it in the ACC. The NTF is fixed accordingly. The string must be terminated with a , or zero byte. Note that the AACC is destroyed in the process and that HL will point to the delimiter at the end of the string. The string formats must follow the same rules as in BASIC.
0E65H-0E67H
Go zero the exponent in REG 1
0E68H-0E6AH
Go set the current number type flag to double precision

0E6CH – ASCII to Binary Converter

  • A call to 0E6CH converts the ASCII string pointed to by HL to binary. If the value is less than 2** 16 and does not contain a decimal point or an E or D descriptor (exponent), the string will be converted to its integer equivalent. If the string contains a decimal point or an E, or D descriptor or if it exceeds 2** 16 it will be converted to single or double precision. The binary value will be left in REG 1 and the mode flag will be to the proper value.
  • Note: If you wanted to do this conversion via a ROM call, first have the characters assembled in consecutive memory locations, with either a comma or a 00H at the end. Load HL with the address of the first character. Call 0E6CH. If the output can be an integer, it will be in 4121H-4122H (with 40AFH being a 2). If the output has to be single precision, it will be in 4121H-4124H (with 40AFH being a 4). If the output has to be double precision, it will be in 411DH-4124H (with 40AFH being an 8).
0E6CH
“ASTOR”
OR 0AFH
Zero Register A (by issuing an OR against 1010 1111).
This routine is the same as E65H above, except that it fixes REG 1 and NTF to the smallest possible number type
0E6DH
EX DE,HL
Load register pair DE with the current input buffer pointer in register pair HL
0E6EH-0E70H
LD BC,00FFH
Load register pair BC with a zero and a negative one
0E71H
LD H,B
Load register H with zero
0E72H
LD L,B
Load register L with zero
0E73H-0E75H
Go set the current number type flag to integer if the routine was entered from OE6CH
0E76H
EX DE,HL
Load register pair HL with the input buffer pointer in register pair DE
0E77H
LD A,(HL)
Load Register A with the character at the location of the current input buffer pointer in register pair HL
0E78H-0E79H
CP 2DH
Check to see if the character at the location of the current input buffer pointer in Register A is a “
0E7AH
PUSH AF
Save the value in register pair AF on the stack
0E7BH-0E7DH
Jump if the character at the location of the current input buffer pointer in Register A is a minus sign (-)
0E7EH-0E7FH
CP 2BH
Check to see if the character at the location of the current input buffer pointer in Register A is a plus sign(+)
0E80H-0E81H
Jump if the character at the location of the current input buffer pointer in Register A is a plus sign ( +)
0E82H
DEC HL
Decrement the value of the current input buffer pointer in register pair HL
0E83H
Since we need to bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H (which Loads the next character from the string pointed to by the HL register set into the A-Register And clears the CARRY flag if it is alphabetic, or sets it if is alphanumeric. Blanks and control codes 09 and OB are ignored causing the following character to be loaded and tested. The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one. The string must be terminated by a byte of zeros)
0E84H-0E86H
Jump if the character at the location of the current input buffer pointer in Register A is numeric
0E87H-0E88H
CP 2EH
Check to see if the character at the location of the current input buffer pointer in Register A is a “.
0E89H-0E8BH
Jump if the character at the location of the current input buffer pointer in Register A is a “.
0ESCH-0E8DH
CP 45H
Check to see if the character at the location of the current input buffer pointer in Register A is an “E
0E8EH-0E8FH
Jump if the character at the location of the current input buffer pointer in Register A is an “E
0E90H-0E91H
CP 25H
Check to see if the character at the location of the current input buffer pointer in Register A is a “&
0E92H-0E94H
Jump if the character at the location of the current input buffer pointer in Register A is a “&
0E95H-0E96H
CP 23H
Check to see if the character at the location of the current input buffer pointer in Register A is a “#
0E97H-0E99H
Jump if the character at the location of the current input buffer pointer in Register A is a “#
0E9AH-0E9BH
CP 21H
Check to see if the character at the location of the current input buffer pointer in Register A is a “!
0E9CH-0E9EH
Jump if the character at the location of the current input buffer pointer in Register A is a “!
0E9FH-0EA0H
CP 44H
Check to see if the character at the location of the current input buffer pointer in Register A is a “D
0EA1H-0EA2H
Jump if the character at the location of the current input buffer pointer in Register A isn’t a “D
0EA3H
OR A
Set the flags according to the value of the character at the location of the current input buffer pointer in Register A
0EA4H-0EA6H
Go convert the current value in REG 1 to either single precision or double precision
0EA7H
PUSH HL
Save the current input buffer pointer in register pair HL on the stack
0EA8H-0EAAH
LD HL,0EBDH
Load register pair HL with the return address (which is 3773)
0EABH
EX (SP),HL
Exchange the return address in register pair HL with the value of the current input buffer pointer in register pair HL
0EACH
Since we need to bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-Register And clears the CARRY flag if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
0EADH
DEC D
Decrement the value in register D
0EAEH-0EAFH
CP 0CEH
Check to see if the character at the location of the current input buffer pointer in Register A is a “
0EB0H
RET Z
Return if the character at the location of the current input buffer pointer in Register A is a minus sign token (CEH)
0EB1H-0EB2H
CP 2DH
Check to see if the character at the location of the current input buffer pointer in Register A is a minus sign(-)
0EB3H
RET Z
Return if the character at the location of the current input buffer pointer in Register A is a “
0EB4H
INC D
Increment the value in register D
0EB5H-0EB6H
CP 0CDH
Check to see if the character at the location of the current input buffer pointer in Register A is a plus sign token (0CDH)
0EB7H
RET Z
Return if the character at the location of the current input buffer pointer in Register A is a plus sign token (CDH)
0EB8H-0EB9H
CP 2BH
Check to see if the character at the location of the current input buffer pointer in Register A is a plus sign ( +)
0EBBH
RET Z
Return if the character at the location of the current input buffer pointer in Register A is a plus sign ( +)
0EBAH
DEC HL
Decrement the value of the input buffer pointer in register pair HL
0EBCH
POP AF
Get the value from the stack and put it in register pair AF
0EBDH
Since we need to bump the current input buffer pointer in register pair HL until it points to the next character, call the EXAMINE NEXT SYMBOL routine at RST 10H.
NOTE:
  • The RST 10H routine loads the next character from the string pointed to by the HL register into the A-Register And clears the CARRY flag if it is alphabetic, or sets it if is alphanumeric.
  • Blanks and control codes 09H and 0BH are ignored causing the following character to be loaded and tested.
  • The HL register will be incremented before loading any character therfore on the first call the HL register should contain the string address minus one.
  • The string must be terminated by a byte of zeros.
0EBEH-0EC0H
Jump if the character at the location of the input buffer pointer in Register A is numeric
0EC1H
INC D
Increment the value in register D
0EC2H-0EC3H
Jump if the exponent is positive
0EC4H
XOR A
Zero Register A
0EC5H
SUB E
Subtract the value of the exponent in register E from Register A
0EC6H
LD E,A
Load register E with the value of the exponent in Register A
0EC7H
PUSH HL
Save the current input buffer pointer in register pair HL on the stack
0EC8H
LD A,E
Load Register A with the value of the exponent in register E
0EC9H
SUB B
Subtract the value in Register B from the exponent in Register A
0ECAH-0ECCH
Go multiply the current value by ten if necessary
0ECDH-0ECFH
Go divide the current value by ten if necessary
0ED0H-0ED1H
Loop until the value is adjusted correctly
0ED2H
POP HL
Get the value of the current input buffer pointer from the stack and put it in register pair HL
0ED3H
POP AF
Get the value from the stack and put it in register pair AF
0ED4H
PUSH HL
Save the value of the current input buffer pointer in register pair HL on the stack
0ED5H-0ED7H
Go convert the current value to negative if necessary
0ED8H
POP HL
Get the value of the current input buffer pointer from the stack and put it in register pair HL
0ED9H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0EDAH
RET PE
If that test shows we have anything other than a SINGLE PRECISION number, return out of the subroutine
0EDBH
PUSH HL
Save the current value of the input buffer pointer in register pair HL on the stack
0EDCH-0EDEH
LD HL,0890H
Load register pair HL with the return address of 2192
0EDFH
PUSH HL
Save the value of the return address in register pair HL on the stack
0EE0H-0EE2H
Go convert the current value in REG 1 to an integer if possible
0EE3H
RET
Return
0EE4H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0EE5H
INC C
Increment the value in register C
0EE6H-0EE7H
If that test shows we have a number, jump to 0EC7H since there is no need to convert the current value
0EE8H-0EEAH
If that test shows we have anything other than DOUBLE PRECISION, go to 0EFBH to convert the current value in REG 1 to single precision
0EEBH-0EEDH
Jump to 0E83H
0EEEH
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0EEFH-0EF1H
If that test shows anything butn an INTEGER, jump to the Level II BASIC error routine and display a SN ERROR message
0EF2H
INC HL
Increment the value of the current input buffer pointer in register pair HL
0EF3H-0EF4H
Jump to 0EC7H
0EF5H
OR A
Set the flags according to the character at the location of the current input buffer pointer in register pair HL
0EF6H-0EF8H
Go convert the current value in REG 1 to either single precision or double precision
0EF9H-0EFAH
Jump to 0EF2H
0EFBH
PUSH HL
Save the value in register pair HL on the stack
0EFCH
PUSH DE
Save the value in register pair DE on the stack
0EFDH
PUSH BC
Save the value in register pair BC on the stack
0EFEH
PUSH AF
Save the value in register pair AF on the stack
0EFFH-0F01H
Call the CONVERT TO SINGLE PRECISION routine at 0AB1H (which converts the contents of REG 1 from integer or double precision into single precision)
0F02H
POP AF
Get the value from the stack and put it in register pair AF
0F03H-0F05H
Call the CONVERT TO DOUBLE PRECISION routine at 0ADBH (where the contents of REG 1 are converted from integer or single precision to double precision)
0F06H
POP BC
Get the value from the stack and put it in register pair BC
0F07H
POP DE
Get the value from the stack and put it in register pair DE
0F08H
POP HL
Get the value from the stack and put it in register pair HL
0F09H
RET
Return
0F0AH
RET Z
Return if the current value is an integer
0F0BH
PUSH AF
Save the value in register pair AF on the stack
0F0CH
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0F0DH
PUSH AF
Save the value in register pair AF on the stack
0F0EH-0F10H
If that test shows SINGLE PRECISION, go to 093EH to multiply the current value in REG 1 by ten
0F11H
POP AF
Get the value from the stack and put it in register pair AF
0F12H-0F14H
If that test shows DOUBLE PRECISION, go to 0E4DH to multiply the current value in REG 1 by ten
0F15H
POP AF
Get the value from the stack and put it in register pair AF
0F16H
DEC A
Decrement the value in Register A
0F17H
RET
Return
0F18H
PUSH DE
Save the value in register pair DE on the stack
0F19H
PUSH HL
Save the value in register pair HL on the stack
0F1AH
PUSH AF
Save the value in register pair AF on the stack
0F1BH
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0F1CH
PUSH AF
Save the value in register pair AF on the stack
0F1DH-0F1FH
If that test shows SINGLE PRECISION, go to 0897H to divide the current value in REG 1 by ten
0F20H
POP AF
Get the value from the stack and put it in register pair AF
0F21H-0F23H
If that test shows DOUBLE PRECISION, go to 0DDCH to divide the current value in REG 1 by ten
0F24H
POP AF
Get the value from the stack and put it in register pair AF
0F25H
POP HL
Get the value from the stack and put it in register pair HL
0F26H
POP DE
Get the value from the stack and put it in register pair DE
0F27H
INC A
Increment the value in Register A
0F28H
RET
Return
0F29H
PUSH DE
Save the value in register pair DE on the stack
0F2AH
LD A,B
Load Register A with the value in Register B
0F2BH
ADC A,C
Add the value in register C to the value in Register A
0F2CH
LD B,A
Load Register B with the adjusted value in Register A
0F2DH
PUSH BC
Save the value in register pair BC on the stack
0F2EH
PUSH HL
Save the value in register pair HL on the stack
0F2FH
LD A,(HL)
Load Register A with the character at the location of the current input buffer pointer in register pair HL
0F30H-0F31H
SUB 30H
Subtract 30H from the ASCII value in Register A so that it will be binary
0F32H
PUSH AF
Save the adjusted value in Register A on the stack
0F33H
We need to check the value of the current number type flag, so we call the TEST DATA MODE routine at RST 20H.
NOTE: The RST 20H routine determines the type of the current value in REG 1 and returns a combination of STATUS flags and unique numeric values in the A Register According to the data mode flag (40AFH).

The results are returned as follows:
  • Integer = NZ/C/M/E and A is -1
  • String = Z/C/P/E and A is 0
  • Single Precision = NZ/C/P/O and A is 1
  • and Double Precision is NZ/NC/P/E and A is 5.
0F34H-0FJ6H
If that test shows we have anything but an INTEGER, jump to 0F5DH
0F37H-0FJ9H
LD HL,(4121H)
Now that we know we have an integer, load register pair HL with the integer value in REG 1
0F3AH-0FJCH
LD DE,0CCDH
Load register pair DE with 3277
0F3DH
Now we need to check to see if the integer value in HL is greater than or equal to 0CCDH (in DE), so we call the COMPARE DE:HL routine, which numerically compares DE and HL. Will not work for signed integers (except positive ones). Uses the A-register only. The result of the comparison is returned in the status Register As: CARRY SET=HL<DE; NO CARRY=HL>DE; NZ=Unequal; Z=Equal)
0F3EH-0FJFH
Jump if the integer value in register pair HL is greater than or equal to 3277
0F40H
LD D,H
Load register D with the MSB of the integer value in register H
0F41H
LD E,L
Load register E with the LSB of the integer value in register L
0F42H
ADD HL,HL
Multiply the integer value in register pair HL by two
0F43H
ADD HL,HL
Multiply the integer value in register pair HL by two. Register pair HL now holds the original integer value times four
0F44H
ADD HL,DE
Add the original integer value in register pair DE to the integer value in register pair HL. Register pair HL now holds the original integer value times five
0F45H
ADD HL,HL
Multiply the integer value in register pair HL by two. Register pair HL now holds the origmal integer value times ten
0F46H
POP AF
Get the binary value for the next character from the stack and put it in Register A
0F47H
LD C,A
Load register C with the value of the character in Register A
0F48H
ADD HL,BC
Add the value of the character in register pair BC to the integer value in register pair HL
0F49H
LD A,H
Load Register A with the MSB of the integer value in register H
0F4AH
OR A
Check to see if the sign bit is set
0F4BH-0F4DH
Jump if the sign bit is set in the integer value in register pair HL
0F4EH-0F50H
LD (4121H),HL
Save the integer value in register pair HL as the current integer value in REG 1
0F51H
POP HL
Get the value from the stack and put it in register pair HL
0F52H
POP BC
Get the value from the stack and put it in register pair BC
0F53H
POP DE
Get the value from the stack and put it in register pair DE
0F54H-0F56H
Jump to 0E83H
0F57H
LD A,C
Load Register A with the binary value of the charac�ter in register C
0F58H
PUSH AF
Save the value in Register A on the stack
0F59H-0F5BH
Go convert the current value in REG 1 to single precision
0F5CH
SCF
Set the Carry flag
0F5DH-0F5EH
Jump if the current value in REG 1 is double preci�sion
0F5FH-0F61H
LD BC,9474H
Load register pair BC with the exponent and the MSB of a single precision constant
0F62H-0F64H
LD DE,2400H
Load register pair DE with the NMSB and the LSB of a single precision constant. Register pairs BC and DE now hold a single precision constant equal to 1E6
0F65H-0F67H
Call the SINGLE PRECISION COMPARISON routine at 0A0CH.

NOTE: The routine at 0A0CH algebraically compares the single precision value in BC/DE to the single precision value REG 1.
The results are stored in A as follows:
  • A=0 if REG 1 = BCDE
  • A=1 if REG 1>BCDE; and
  • A=FFH if REG 1<BCDE.
0F68H-0F6AH
Jump if the single precision value in REG 1 is greater than or equal to 1E6
0F6BH-0F6DH
Go multiply the single precision value in REG 1 by 10
0F6EH
POP AF
Get the binary value of the character from the stack and put it in Register A
0F6FH-0F71H
Go add the value in Register A to the single precision value in REG 1
0F72H-0F33H
Jump to 0F51H
0F74H-0F76H
Go convert the single precision value in REG 1 to double precision
0F77H-0F79H
Go multiply the double precision value in REG 1 by ten
0F7AH-0F7CH
Go move the double precision value in REG 1 to REG 2
0F7DH
POP AF
Get the binary value for the character from the stack and put it in Register A
0F7EH-0F80H
Go convert the binary value in Register A to single precision
0F81H-0F83H
Go convert the single precision value in REG 1 to double precision
0F84H-0F86H
Call the DOUBLE PRECISION ADD function (whcih adds the double precision value in REG 2 to the value in REG 1. Result is left in REG 1)
0F87H-0F88H
Jump to 0F51H

0F89H-0F93H – SINGLE PRECISION MATH ROUTINE

0F89H-0F8BH
Call 09A4 which moves the SINGLE PRECISION value in REG 1 to the stack (stored in LSB/MSB/Exponent order)
0F8CH-0F8EH
Go convert the value in Register Ato single precision and return with the result in REG 1
0F8FH
POP BC
Get the exponent and the MSB for the single preci�sion value from the stack and put it in register pair BC
0F90H
POP DE
Get the NMSB and the LSB of the single precision value from the stack and put it in register pair DE
0F91H-0F93H
Jump to the SINGLE PRECISION ADD routine at 0716H (which adds the single precision value in (BC/DE) to the single precision value in REG 1. The sum is left in REG 1)

0F94H-0FA6H – LEVEL II BASIC MATH ROUTINE

0F94H
LD A,E
Load Register A with the value of the exponent in register E
0F95H-0F96H
CP 0AH
Check to see if the value of the exponent in Register A is greater than or equal to 10
0F97H-0F98H
Jump if the value of the exponent in Register A is greater than or equal to 10
0F99H
RLCA
Multiply the value in Register A by two
0F9AH
RLCA
Multiply the value in Register A by two. Register A now holds the original value of the exponent times four
0F9BH
ADD A,E
Add the original value of the exponent in register E to the adjusted value of the exponent in Register A
0F9CH
RLCA
Multiply the value in Register A by two. Register A now holds the original value of the exponent times ten
0F9DH
ADD A,(HL)
Add the value of the current character at the location of the input buffer pointer in register pair HL to the adjusted value in Register A
0F9EH-0F9FH
SUB 30H
Convert the adjusted value in Register A to it’s binary equivalent (which is subtracting 0011 0000)
0FA0H
LD E,A
Load register E with the adjusted value in Register A
0FA2H-0FA3H
JP M,321EH
Load register E with the maximum exponent
0FA4H-0FA6H
Jump to 0EBDH

0FA7H-0FAEH – DISPLAY MESSAGE ROUTINE

0FA7H
PUSH HL
Save the value in register pair HL on the stack
0FA8H-0FAAH
LD HL,1924H
Load register pair HL with the starting address of the IN message (which is 1924H)
0FABH-0FADH
Call the WRITE MESSAGE routine at 28A7H..
NOTE:
  • The routine at 28A7 displays the message pointed to by HL on current system output device (usually video).
  • The string to be displayed must be terminated by a byte of machine zeros or a carriage return code 0D.
  • If terminated with a carriage return, control is returned to the caller after taking the DOS exit at 41D0H (JP 5B99H).
0FAEH
POP HL
Get the value from the stack and put it in register pair HL

0FAFH-0FBCH – CONVERT BINARY TO ASCII AND DISPLAY RESULT

This routine converts the value in the HL register pair (which is assumed to be an integer) to ASCII and display it at the current cursor position on the video screen.

0FAFH-0FB1H
Go save the value in register pair HL as the current value in REG 1
0FB2H
XOR A
Zero Register A
0FB3H-0FB5H
Go initialize the input buffer for the ASCII conver�sion
0FB6H
OR (HL)
Set the flags
0FB7H-0FB9H
Go convert the integer value in REG 1 to an ASCII string. Return with register pair HL pointing to the result
0FBAH-0FBCH
Go display the message pointed to by register pair HL

0FBDH-1363H – BINARY TO ASCII CONVERSION ROUTINE
“CSAASC”

  • Conversion routine. Converts the value from REG 1 to an ASCII string delimited with a zero byte. The number type can be any of Integer, single or double-precision. After execution HL will be pointing to the start of the string. REG 1 and AACC are destroyed by the process.
  • To use a ROM call to convert a number to a string of digits, and to display the latter on the video screen starting at the current cursor position, store the number in 4121H-4122H (if it’s an integer), or in 4121H-4124H (if it’s single precision), or in 411DH-4124H (if it’s double precision). Then store the variable type (2, 4, or 8, respectively) in 40AFH. Call 0FBDH and then call the WRITE MESSAGE routine at 28A7H.
    • NOTE 1: The routine at 0FBDH is the conversion routine described in Section 3.3 (a). The subroutine at 28A7H is a general program for displaying a string of characters and updating the cursor position. The string to be displayed must be terminated by a zero byte, and the HL register pair must contain the address of the first character of the string before 28A7H is called. (The routine at 0FBDH effects this setup automatically.)
    • NOTE 2: Many of the ROM routines described in this book require a numeric input (or inputs). For most of these, the instructions given for calling them have not included the storage of the variable type flag in 40AFH. The reason is that, wherever possible, the variable type flag storage has been finessed by the choice of the subroutine entry point. In the routine of this section, that has not been possible, nor was it possible for the INT, the FIX, the Number to Numeric String, the SGN, or the ABS routines. Storing a 2, 4, or 8 in 40AFH takes only 5 bytes of machine code, but there are subroutines in the Level II ROM that can reduce the required code to 3 bytes. CALL 0A9DH will store a 2 in 40AFH. CALL 0AEFH will store a 4 in 40AFH. And, finally, CALL 0AECH will store an 8 in 40AFH; this last subroutine, however, destroys the contents of the BC register pair. DISK SYSTEM CAUTION: The subroutine at 28A7H has two exits to DISK BASIC, with RAM transfer points at 41C1H and 41D0H. To use this routine safely, either be certain that DISK BASIC is in place or have your assembly language program fill locations 41C1H and 41D0H with RET’s (C9H), before calling the routine.
0FBDH
“NEDIT”
XOR A
Zero Register A

0FBEH-0FC0H – FLOATING to ASCII Conversion Routine

  • This routine converts a single or double precision number in REG 1 to its ASCII equivalent. The ASCII value is stored at the buffer pointed to by the HL register pair. As the value is converted from binary to ASCII, it is formatted as it would be if a PRINT USING statement had been invoked. The format modes that can be specified are selected by loading the following values into the A, B, and C registers as follows:
    • A=0 means do not edit; this is a binary to ASCII conversion
    • A=X means edit as follows: Bit 7=1 means edit the value, Bit 6=Print commas every third digit, Bit 5=Include leading asterisks, Bit 4=Print a leading $, Bit 3=Sign Follows Value, and Bit 1=Exponential Notation
    • B = The number of digits to the left of the decimal point.
    • C = The number of digits after the decimal point.
  • Note: If you wanted to convert any integer/single/double into its character string, store the variable in 4121H-4122H for integer, 4121H-4124H for single, or in 411DH-4124H for double. Then load 40AFH with a 2, 4, or 8 depending on whether that variable was integer, single, or double. Then call 0FBDH. Upon return, the character string is stored in 4130H and on, ending with a 00H.
0FBEH-0FC0H
“FEDIT”
Initialize the input buffer for the ASCII conversion by calling 1034H (which puts the EDIT flag into A, loads HL with the starting address of the input buffer, and inserts a space)
0FC1H-0FC2H
AND 08H
Check the value of the edit flag in Register A to see if the sign is to be included
0FC3H-0FC4H
Jump to 0FC7H if the sign isn’t to be included in the ASCII string
0FC5H-0FC6H
LD (HL),2BH
Save a plus sign (+)at the location of the input buffer pointer in register pair HL
0FC7H
EX DE,HL
Load register pair DE with the value of the input buffer pointer in register pair HL
0FC8H-0FCAH
Go determine the value of the sign for the current value in REG 1
0FCBH
EX DE,HL
Load register pair HL with the input buffer pointer in register pair DE
0FCCH-0FCEH
Jump down to 0FD9H if the current value in REG 1 is positive
0FCFH-0FD0H
LD (HL),2DH
Save a minus sign (-) at the location of the input buffer pointer in register pair HL
0FD1H
PUSH BC
Save the value in register pair BC on the stack
0FD2H
PUSH HL
Save the value in register pair HL on the stack
0FD3H-0FD5H
Gosub to 097BH to convert the negative value in REG 1 to it’s positive equivalent
0FD6H
POP HL
Get the value from the stack and put it in register pair HL
0FD7H
POP BC
Get the value from the stack and put it in register pair HL
0FD8H
OR H
Set the flags
OFD9H
INC HL
Increment the input buffer pointer in register pair HL
0FDAH-0FDBH
LD (HL),30H
Save an ASCII zero (0) at the location of the input buffer pointer in register pair HL
0FDCH-0FDEH
LD A,(40D8H)
Load Register A with the value of the edit flag (stored at 16600).
Note: 40D8H-40D9H holds the temporary storage location
0FDFH
LD D,A
Load register D with the value of the edit flag in Register A
0FE0H
RLA
Move the edit on/off bit in Register A into the Carry flag
0FE1H-0FE3H
LD A,(40AFH)
Load Register A with the value of the current number type flag (stored at 16559).
Note: 40AFH holds Current number type flag (-1, 0, 1, or 5)
0FE4H-0FE6H
Jump to 109AH if value is to be edited
0FE7H-0FE9H
Jump to 1092H if no edit
0FEAH-0FEBH
CP 04H
Check to see if the current value in REG 1 is single or double precision
0FECH-0FEEH
Jump if the current value in REG 1 is single or double precision
0FEFH-0FF1H
LD BC,0000H
Load register pair BC with zero
0FF2H-0FF4H
Call the INTEGER TO ASCII routine at 1232F (which converts the integer in REG 1 to ASCII and stores the ASCII string in the buffer pointed to in HL)
0FF5H-0FF7H
LD HL,4130H
Load register pair HL with the starting address of the input buffer, which is at 16688.
Note: 4130H-4149H holds Internal print buffer
0FF8H
LD B,(HL)
Load Register B with the character at the location of the input buffer pointer in register pair HL
0FF9H-0FFAH
LD C,20H
Load register C with a space character
0FFBH-0FFDH
LD A,(40D8H)
Load Register A with the value of the edit flag (which is stored in 40D8H).
Note: 40D8H-40D9H holds the temporary storage location
0FFEH
LD E,A
Load register E with the value of the edit flag in Register A
0FFFH-1000H
AND 20H
Check the value of the edit flag in Register A (by AND against 0010 0000) to see if leading * are to be printed