[sourcecode language="plain"]
DEFINE NOT_HOMEROM
ORG 0
INCLUDE "2068_DEFS.ASM"
; Home ROM addresses
DEFC LED18 = $0E2F
;DEFC XFER_BYTES = $6722
DEFC MFD32 = $FD32
DEFC M6000 = $6000
DEFC MFD90 = $FD90
DEFC M255D = $255D
DEFC DATTYPE = $00
DEFC FILENAME = $01
DEFC BLKLEN = $0B
DEFC ARG1 = $0D
DEFC ARG2 = $0F
;******************************************************************
; Module:
; Routine:
; general routines used when the EXROM is switched in
;******************************************************************
XRST0: DI ;disable interrupts
JR M0049 ;jump to bank transfer code
DEFB $FF,$FF,$FF,$FF,$FF
;local RST 8 error handler.
XRST8: LD HL,(CHADD) ;HL gets the address of the character
; in dispute
LD (XPTR),HL ;put it into the "syntax error" character
; pointer
POP HL ;get the caller's address
LD L,(HL) ;/put the error code into
LD (IY+OERRNR),L ;\ ERRNR
LD SP,(ERRSP) ;get the error stack pointer
;jump to the home bank to handle the error
LD HL,RESET ;/address for goto bank
PUSH HL ;\
LD H,$FF ;/HOME bank ...
LD L,$00 ;|... all chunks
PUSH HL ;\
;fall through to GOTO_BANK
XRST20: PUSH AF ;save AF
LD A,(VIDMOD) ;/
AND A ;|check the video mode
NOP ;\
JR Z,M002C ;jump if normal video
XRST28: POP AF ;restore AF
CALL (($5200+GOTO_BANK+$97C0)~$FFFF) ;jump to RAM INT service when
; in extended video mode
M002C: POP AF ;restore AF
CALL ($5200+GOTO_BANK) ;jump to RAM service when
; in normal video mode
XRST30: DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
;******************************************************************
; Interrupt routine. called when the keyboard interrupt is
; received from the SCLD
;******************************************************************
XRST38: PUSH AF ;save AF
DI ;disable interrupts
LD A,(VIDMOD) ;/
AND A ;|check the video mode
NOP ;\
JR Z,M0045 ;jump if normal video
POP AF ;restore AF
JP INT+$E9C0~$FFFF ;jump to RAM INT service when
; in extended video mode
M0045: POP AF ;restore AF
JP INT+$5200 ;jump to RAM INT service when
; in normal video mode
;******************************************************************
; code executed on power-up if the SCLD has reset to in such a
; state so as to point to EXROM
;******************************************************************
M0049: LD A,$01 ;set HSR to point lower 8K to DOCK/EXROM
OUT ($F4),A ;
JR M005A
;******************************************************************
; this section of code is transferred to HOME RAM by the code
; fragment at M005A during reset, then it is jumped to by the fragment
;
;execution of the following code will cause execution to transfer to the HOME bank
; at location $0054.
XOR A ;/set HSR and EXROM/DOCK select to point to HOME bank
OUT ($F4),A ;|HSR now selects all chunks to HOME/EXROM
OUT ($FF),A ;\bank select now transfers us to HOME
LD DE,$FFFF ;
JP M0D31
;******************************************************************
M005A: LD HL,$004F ;/
LD DE,$6000 ;|transfer the code fragment
LD BC,$000B ;| from above to HOME ROM
LDIR ;\
JP M6000 ;jump to it
;******************************************************************
; Module: TAPE
; Routine: W_TAPE
;
;
;******************************************************************
W_TAPE:
M0068: LD HL,$00E5 ;
PUSH HL ;
;set the number of header half cycles based on A. if A>$7F, write a
; data block header else write a file header
LD HL,$1F80 ;number of half-cycles for the
; header
BIT 7,A ;/skip if header
JR Z,M0076 ;\
LD HL,$0C98 ;number of half-cycles for the
; data header
M0076: EX AF,AF' ;save the data byte
INC DE ;/preadjust the counters for the following
DEC IX ;\ processing
DI ;don't interrupt the the tape output
LD A,$02 ;/start sound with '0' and set border red
LD B,A ;\(alternates with cyan)
;write the tape header
M007E: DJNZ M007E ;delay loop for tone output
OUT ($FE),A ;activate tape output bit
XOR $0F ;flip the border color and tape output signal
LD B,$A4 ;half-cycle time for 806.5Hz
DEC L ;/jump if header not done
JR NZ,M007E ;\
DEC B ;adjust B for processing time
DEC H ;/jump if header not done
JP P,M007E ;\
;hokay, the header has now been written, so move on to writing the data
;write the single 2400Hz transition
LD B,$2F ;first half-cycle of the 2400Hz transition
M0090: DJNZ M0090 ;(adjusted for processing time)
OUT ($FE),A ;
LD A,$0D ;second half-cycle of the transition
LD B,$37
M0098: DJNZ M0098
OUT ($FE),A
LD BC,$3B0E ;B=half-cycle freq for 2400Hz, Tape output high, border = YELLOW
EX AF,AF' ;get the type byte
LD L,A ;save in L
JP M00AD ;off to the races
M00A4: LD A,D ;/jump if the byte counter is '0';
OR E ;|last byte to be written
JR Z,M00B4 ;\ (send the checksum)
LD L,(IX+$00) ;get the next byte
M00AB: LD A,H ;get checksum
XOR L ;XOR next byte to be sent
M00AD: LD H,A ;save the checksum
LD A,$01 ;Tape output low, border = BLUE
SCF ;sentinal bit, byte to be sent will be zero only
; when all 8 bits have been shifted out
JP M00CB ;start sending the byte
M00B4: LD L,H ;get the checksum
JR M00AB ;send it
M00B7: LD A,C ;Tape output high, border = YELLOW
BIT 7,B ;this will indicate that the 2nd half-cycle has
; been sent
;output the data bit in the CF
M00BA: DJNZ M00BA ;wait a half-cycle
JR NC,M00C2 ;jump if data bit is '0'
LD B,$42 ;/wait a bit longer for a '1'
M00C0: DJNZ M00C0 ;\
M00C2: OUT ($FE),A ;flip the bit
LD B,$3E ;half-cycle for '0'
JR NZ,M00B7 ;jump if next half-cycle is still to be sent
DEC B ;B = $3D (make up for processing time)
XOR A ;zero A (and reset carry flag)
INC A ;A=1
M00CB: RL L ;get the next bit of the byte to send
JP NZ,M00BA ;jump if bits are still left to be sent
DEC DE ;decrement the byte count
INC IX ;point to the next byte to send
LD B,$31 ;half-cycle value for a '0'
LD A,$7F ;precharge the A register
IN A,($FE) ;read the keyboard
RRA ;/return if key press detected
RET NC ;\
LD A,D ;/continue if more bytes are waiting
INC A ;|to be written
JP NZ,M00A4 ;\(carry will be set on exit, indicating all is OK)
LD B,$3B ;/wait for one last half-cycle
M00E2: DJNZ M00E2 ;\
RET ;our job here is done
;******************************************************************
; Module: TAPE
; Routine: W_BORD
;******************************************************************
W_BORD:
PUSH AF ;save AF
LD A,(BORDCR) ;get attribute
AND $38 ;/
RRCA ;|form port compatible border
RRCA ;|color value
RRCA ;\
OUT ($FE),A ;set the border color
LD A,$7F ;/
IN A,($FE) ;|check keyboard
RRA ;\
EI ;enable interrupts
JR C,M00FA ;jump if no key pressed
RST $08 ;/error BREAK
DEFB $0C ;\
M00FA: POP AF ;restore AF
RET ;done
;******************************************************************
; Module: TAPE
; Routine: R_TAPE
; ENTRY: IX points to the destination, DE is the block length to load
;******************************************************************
R_TAPE:
M00FC: INC D ;
EX AF,AF' ;
DEC D ;
DI ;don't interrupt us
LD A,$0F ;/set tape out=high,border to WHITE
OUT ($FE),A ;\
LD HL,$00E5 ;
PUSH HL ;
IN A,($FE) ;get tape input
RRA ;tape bit is now in the $20 position
AND $20 ;mask for the tape bit
OR $02 ;set bit 1
LD C,A ;save the seed value for the call to R_EDGE
CP A ;ensure we don't return before we call R_EDGE
M0111: RET NZ ;return if tape bit is not high
M0112: CALL R_EDGE ;check for transition on the tape input
JR NC,M0111 ; a key was pressed, so abort
;there was a transition detected, so let's try to read the tape.
; wait for 1044 bit times: this is a significant fraction of the time needed
; for either of the headers
LD HL,$0415 ;for 1044 bits
M011A: DJNZ M011A ;wait for the length of time returned by R_EDGE
; at M0112
DEC HL ;/
LD A,H ;|jump if HL is not zero
OR L ;|
JR NZ,M011A ;\
CALL M0189 ;get a bit of data
JR NC,M0111 ;error detected, so exit
;check for header
M0126: LD B,$9C ;
CALL M0189 ;get a bit of data
JR NC,M0111 ;error detected, so exit
LD A,$C6 ;/
CP B ;|jump if 806.5Hz detected?
JR NC,M0112 ;\
INC H ;
JR NZ,M0126 ;jump back if not enough cycles detected
M0135: LD B,$C9 ;
CALL R_EDGE ;check again for the edge of a bit
JR NC,M0111 ;error detected, so exit
LD A,B ;
CP $D4 ;
JR NC,M0135 ;
CALL R_EDGE ;check for the edge of a bit
RET NC ;error detected, so exit
LD A,C ;
XOR $03 ;
LD C,A ;
LD H,$00 ;
LD B,$B0 ;
JR M016E ;
M014F: EX AF,AF' ;
JR NZ,M0159 ;
JR NC,M0163 ;
LD (IX+$00),L ;save received byte at (IX)
JR M0168 ;
M0159: RL C ;
XOR L ;
RET NZ ;
LD A,C ;
RRA ;
LD C,A ;
INC DE ;
JR M016A ;
M0163: LD A,(IX+$00) ;get the last byte received
XOR L ;check tha check sum
RET NZ ;return if the checksum is in error
M0168: INC IX ;bump the pointer
M016A: DEC DE ;decrement the block length
EX AF,AF' ;
LD B,$B2 ;
M016E: LD L,$01 ;
M0170: CALL RD_BIT ;read a bit
RET NC ;error detected, so return
LD A,$CB ;
CP B ;
RL L ;
LD B,$B0 ;
JP NC,M0170 ;
LD A,H ;
XOR L ;
LD H,A ;
LD A,D ;
OR E ;
JR NZ,M014F ;
LD A,H ;
CP $01 ;
RET ;
;******************************************************************
; Module: TAPE
; Routine: RD_BIT
;******************************************************************
RD_BIT:
M0189: CALL R_EDGE ;find the tape tone
RET NC ;return if error detected, else
; move on to detect the next edge
;******************************************************************
; Module: TAPE
; Routine: R_EDGE
; find the edge of a tape tone.
; ENTRY: B contains a value through which to wait
;******************************************************************
R_EDGE:
M018D: LD A,$16 ;/
M018F: DEC A ;|wait a 70uS 4
JR NZ,M018F ;\ 7/12
AND A ;reset CF
M0193: INC B ;bump the timer? 4
RET Z ;return if we have waited a long time? 10
LD A,$7F ;/ 7
IN A,($FE) ;|read the keyboard and the tape input bit
RRA ;|(puts tape bit into $20 position and loads
;\LSB of key scan into the carry flag)
RET NC ;return if key is pressed
XOR C ;/this checks if there has been a transition
;| of the tape bit
AND $20 ;\check the tape in bit
JR Z,M0193 ;jump if this tape sample is the same as the
; last sample - wait for the transition
LD A,C ;get previous tape input bit value
CPL ;complement it
LD C,A ;save it again
AND $07 ;mask for the BORDER color
OR $08 ;set the tape out bit (echo the sound on the
; tape)
OUT ($FE),A ;output the new border color and tape bit
SCF ;indicate all is OK
RET ;weebiedun
;******************************************************************
; Module: TAPE
; Routine: SLVM
; "Save, Load, Verify, Merge"
; this routine does the donkey work of parsing the command line for
; the tape functions.
; ENTRY: (TADDR) is used to differentiate between
; "LOAD", "SAVE", "VERIFY", or "MERGE"
;******************************************************************
SLVM: LD A,(TADDR) ;low byte of the syntax table pointer
LD BC,PASAVE+1 ;address of PASAVE in the syntax table
SUB C ;generate a value based on the instruction
; kinda cheesy, but seems to work.
LD (TADDR),A ;(TADDR)= 0 for SAVE
; 1 for LOAD
; 2 for VERIFY
; 3 for MERGE
;get the file name. the string parameters will be on the top of the fp stack
; CALLBANKS TEM10,HOMEROM,$00 ;evaluate the next expression and return here if it is a string
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,TEM10 ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
BIT INTPT,(IY+$01) ;/jump if syntax checking
JR Z,M0238 ;\
;prepare to allocate a 17 byte header buffer if the value at TADDR is zero (SAVE)
LD BC,$0011 ;
LD A,(TADDR) ;/jump if SAVE (only one buffer needed)
AND A ;|
JR Z,M01DD ;\
;allocate two header buffers worth of memory. this is needed for
; LOAD, VERIFY, and MERGE. one buffer for the stuff coming from tape, the other
; for the arguments coming from the command line. DE points to the start of the
; newly allocated memory
LD C,$22 ;
M01DD:
;M01DD: CALLBANKS ALLOCBC,HOMEROM,$00 ;allocate the header buffer
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,ALLOCBC ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
;we will return here if the buffer could be allocated
PUSH DE ;/copy the location of the header buffer
POP IX ;\ to IX
LD B,$0B ;/
LD A,' ' ;|fill up the program name with
M01FB: LD (DE),A ;|spaces
INC DE ;|
DJNZ M01FB ;\
LD (IX+FILENAME),$FF ;indicate no name present
; check the name provided to the command
;get the string descriptor from the fp stack
; CALLBANKS PGPSTR,HOMEROM,$00 ;pop BC, DE, and A from fp stack
PUSH IX
EXX
LD HL,PGPSTR ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
LD HL,-10 ;/test the length of the program name
DEC BC ;|(a length of zero will cause an overflow
ADD HL,BC ;\ hence an error)
INC BC ;restore BC
JR NC,M0231 ;jump if the name was less than 11 characters
LD A,(TADDR) ;/jump if this command does not REQUIRE a name
AND A ;| LOAD, MERGE, VERIFY
JR NZ,M022A ;\
RST $08 ;/error F - invalid file name
DEFB $0E ;\
M022A: LD A,B ;/jump if the length of the name is zero
OR C ;|(no name to move, so don't)
JR Z,M0238 ;\
LD BC,$000A ;length of a program name (transfer only the first 10
; characters)
M0231: PUSH IX ;save the header header buffer pointer
POP HL ;get the header buffer pointer to HL
INC HL ;
EX DE,HL ;HL now points to the name, DE points to the header buffer
LDIR ;move the name to the header buffer
;
;now to check the variants of save/load e.g.
; SAVE f LINE m, SAVE f DATA A(), SAVE f DATA A$(), SAVE f CODE m,n, SAVE f SCREEN$
;
M0238:
;M0238: CALLBANKS GETCURCH,HOMEROM,$00 ;call GETCURCH, get
; current character
; skipping spaces and
; control characters
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,GETCURCH ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
CP $E4 ;/jump if not "DATA" token
JP NZ,M02F2 ;\
;
;next, find the DATA item
;
LD A,(TADDR) ;/determine if we are MERGE-ing
CP $03 ;\
JP Z ,BADBAS ;declare a syntax error if so -
; can't MERGE DATA
;get the next character and then attempt to find it in the variables
; area will gobble the "(" of a numeric array or "$(" of a string array name
; CALLBANKD M0020,HOMEROM,$00,FIND_N,HOMEROM,$00
;CALLBANKD: MACRO CALLADR1,DESTBANK1,HORIZSEL1,CALLADR2,DESTBANK2,HORIZSEL2
PUSH IX
EXX
LD HL,M0020 ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
EXX
LD HL,FIND_N ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
SET 7,C ;force an array name
JR NC,M0295 ;jump if we found the variable name
LD HL,$0000 ;trash the pointer to the
; non-existant variable
LD A,(TADDR) ;/jump if we were LOADing
DEC A ;|(variable name not needed; the file
JR Z,M02A9 ;\ header will supply it)
RST $08 ;/error VARIABLE NOT FOUND
DEFB $01 ;\
SLVBADBAS:
M0295: JP NZ,BADBAS ;variable found was not an array variable or a string
BIT 7,(IY+$01) ;/jump if syntax checking
JR Z,M02B6 ;\
INC HL ;/
LD A,(HL) ;|
LD (IX+BLKLEN),A ;|put the length of the variable
INC HL ;| data structure in the header buffer
LD A,(HL) ;|
LD (IX+BLKLEN+1),A ;\
INC HL ;/save data type marker in buffer
M02A9: LD (IX+ARG1+1),C ;\
LD A,$01 ;flag byte
BIT 6,C ;/jump if dealing with numbers
JR Z,M02B3 ;\
INC A ;/put flag (1 for strings, 2 for numbers)
M02B3: LD (IX+DATTYPE),A ;\ in the buffer
M02B6: EX DE,HL ;
; CALLBANKS M0020,HOMEROM,$00 ;get the next character
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,M0020 ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
CP ')' ;/jump if not close paren
JR NZ,SLVBADBAS ;\ [must be there for SAVE f DATA xx()]
; CALLBANKS M0020,HOMEROM,$00 ;get the next character
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,M0020 ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
BIT 7,(IY+$01) ;/return if syntax checking - we are done
RET Z ;\
EX DE,HL ;
JP M04C9 ;
M02F2: CP $AA ;/jump if not "SCREEN$" token
JR NZ,M032E ;\
LD A,(TADDR) ;/syntax error if trying to MERGE
CP $03 ;| can't MERGE SCREEN$ data
JP Z ,BADBAS ;\
; CALLBANKS M0020,HOMEROM,$00 ;get the next character
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,M0020 ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
BIT 7,(IY+$01) ;/return if syntax checing
RET Z ;\
LD (IX+BLKLEN),00 ;/load screen length into buffer
LD (IX+BLKLEN+1),$1B ;\
LD HL,$4000 ;/screen address
LD (IX+ARG1),L ;|
LD (IX+ARG1+1),H ;\
JP M0440 ;
M032E: CP $AF ;/jump if not "CODE" token
JP NZ,M0447 ;\
LD A,(TADDR) ;/
CP $03 ;|syntax error if trying to MERGE
JP Z ,BADBAS ;\
;get the next character and then check to see if we are at the end
; of a statement (":" or newline)
; CALLBANKD M0020,HOMEROM,$00,TERM?,HOMEROM,$00
;CALLBANKD: MACRO CALLADR1,DESTBANK1,HORIZSEL1,CALLADR2,DESTBANK2,HORIZSEL2
PUSH IX
EXX
LD HL,M0020 ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
EXX
LD HL,TERM ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
JR NZ,M0387 ;jump if not the end of a statement
LD A,(TADDR) ;/
AND A ;|syntax error if trying to SAVE
JP Z ,BADBAS ;\
;stack a dummy argument
; CALLBANKS STKFP0,HOMEROM,$00 ;stack a zero on the fp staack
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,STKFP0 ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
JR M03BC ;proceed
;evaluate the next expression. it is numeric we will return here
; to then get the next character
M0387:
;M0387: CALLBANKD TEM6,HOMEROM,$00,GETCURCH,HOMEROM,$00
;CALLBANKD: MACRO CALLADR1,DESTBANK1,HORIZSEL1,CALLADR2,DESTBANK2,HORIZSEL2
PUSH IX
EXX
LD HL,TEM6 ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
EXX
LD HL,GETCURCH ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
CP ',' ;/jump if comma
JR Z,M03D5 ;\
LD A,(TADDR) ;/syntax error if trying to SAVE
AND A ;| must have address and length
JP Z ,BADBAS ;\
;stack a second dummy argument
M03BC:
;M03BC: CALLBANKS STKFP0,HOMEROM,$00 ;stack 0 to the fp stack
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,STKFP0 ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
JR M03FF ;(03FF)
;get the next character then evaluate the next expression. if numeric we
; will return here
M03D5:
;M03D5: CALLBANKD M0020,HOMEROM,$00,TEM6,HOMEROM,$00
;CALLBANKD: MACRO CALLADR1,DESTBANK1,HORIZSEL1,CALLADR2,DESTBANK2,HORIZSEL2
PUSH IX
EXX
LD HL,M0020 ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
EXX
LD HL,TEM6 ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
M03FF: BIT 7,(IY+$01) ;/return if syntax checking - we are done
RET Z ;\
;put the top of the FP stack into BC
; CALLBANKS FIX_U,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,FIX_U ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
LD (IX+BLKLEN),C ;/put the length of the code segment
LD (IX+BLKLEN+1),B ;\ into the buffer
;put the top of the FP stack into BC
; CALLBANKS FIX_U,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,FIX_U ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
LD (IX+ARG1),C ;/put the address of the code segment
LD (IX+ARG1+1),B ;\ into the buffer
LD H,B ;/put the code address into HL
LD L,C ;\
M0440: LD (IX+DATTYPE),03 ;put the file type into the buffer - BINARY
JP M04C9 ;jump to determine if we are SAVEing
M0447: CP $CA ;/jump if "LINE" token
JR Z,M0456 ;\
BIT 7,(IY+$01) ;/return if syntax checking
RET Z ;\
LD (IX+ARG1+1),$80 ;/no line number specified
JR M04A9 ;\
M0456: LD A,(TADDR) ;/
AND A ;|syntax error if NOT trying to SAVE
JP NZ,BADBAS ;\
;get the next character and then evaluate the next expression.
; return here if its numeric
; CALLBANKD M0020,HOMEROM,$00,TEM6,HOMEROM,$00
;CALLBANKD: MACRO CALLADR1,DESTBANK1,HORIZSEL1,CALLADR2,DESTBANK2,HORIZSEL2
PUSH IX
EXX
LD HL,M0020 ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
EXX
LD HL,TEM6 ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
BIT 7,(IY+$01) ;/return if syntax checking
RET Z ;\
;put the top of the FP stack into BC
; CALLBANKS FIX_U,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,FIX_U ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
LD (IX+ARG1),C ;/put the line number into the buffer
LD (IX+ARG1+1),B ;\
M04A9: LD (IX+$00),00 ;put file type into the buffer
LD HL,(ELINE) ;/
LD DE,(PROG) ;|compute the length of the program
SCF ;|and variables to the $80 byte
SBC HL,DE ;\just after the variables
LD (IX+BLKLEN),L ;/block length to the
LD (IX+BLKLEN+1),H ;\buffer
LD HL,(VARS) ;/compute the variables area length
SBC HL,DE ;\
LD (IX+ARG2),L ;/length of the variables
LD (IX+ARG2+1),H ;\to the buffer
EX DE,HL ;DE=length, HL=(VARS)
M04C9: LD A,(TADDR) ;/
AND A ;|jump if we are SAVEing
JP Z,SAVE ;\
PUSH HL ;save the block length
LD BC,$0011 ;/point to the buffer used to store
ADD IX,BC ;\ the header coming in from the tape
M04D6: PUSH IX ;save the header
LD DE,$0011 ;length of the header
XOR A ;reset the carry and zero the accumulator
SCF ;set the carry flag ("LOAD" the tape)
;read the program header
CALL R_TAPE ;read the tape
POP IX ;restore the header pointer
JR NC,M04D6 ;loop around for unsuccessful load
; (break or error)
LD A,$FE ;select channel -2
; CALLBANKS SELECT,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,SELECT ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
LD (IY+$52),03 ;load the scroll count with 3
LD C,$80 ;
LD A,(IX+DATTYPE) ;/compare the file type from the
CP (IX+(-$11)) ;\tape with the file type from the command line
JR NZ,M050D ;not the same, so check if it is a TS file
LD C,$F6 ;-10
M050D: CP $04 ;
JR NC,M04D6 ;we found a non TS file type, so back around
;
;we found some type of file so tell the user so
;
LD DE,$3CA8 ; address of "Program: " message
PUSH BC ;briefly save C
;print a message to the current channel. A contains the number of the message to
; be printed
; CALLBANKS PUTMES,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,PUTMES ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
POP BC ;restore BC
PUSH IX ;save buffer pointer
POP DE ;get it to DE
LD HL,-16 ;/subtract 16 from the buffer pointer
ADD HL,DE ;\ DE points to the second buffer name
LD B,$0A ;name length counter
LD A,(HL) ;get the first letter of the file name
INC A ;/jump if a name was given (<>$FF)
JR NZ,M053D ;\
LD A,C ;load a with the length of the name
ADD A,B ;add to the max length of a name
LD C,A ;save the length of the name
;
;loop to write the file name
;
M053D: INC DE ;/get a character from the buffer pointer
LD A,(DE) ;\ (we preincrement to get past the data type on the first iteration)
CP (HL) ;compare it to the received name
INC HL ;move along
JR NZ,M0544 ;jump if it does not match
INC C ;if it does match, increment the match counter
;write the character in A
M0544:
;M0544: CALLBANKS WRCH,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,WRCH ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
DJNZ M053D ;back around for another name
BIT 7,C ;/if the names matched, C will have rolled over
JP NZ,M04D6 ;\
;print a newline
LD A,$0D ;newline
; CALLBANKS WRCH,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,WRCH ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
POP HL ;
LD A,(IX+DATTYPE) ;get the data type
CP $03 ;/jump if it is "CODE"
JR Z,M058F ;\
LD A,(TADDR) ;/
DEC A ;|jump to LOAD
JP Z ,M05CC ;\
CP $02 ;/jump if character array
JP Z ,M06E5 ;\
M058F: PUSH HL ;
LD L,(IX+(-$06)) ;/get second buffer block length
LD H,(IX+(-$05)) ;\
LD E,(IX+BLKLEN) ;/get this block length
LD D,(IX+BLKLEN+1) ;\
LD A,H ;/
OR L ;|jump if HL = 0
JR Z,M05AD ;\
SBC HL,DE ;
JR C,M05CA ;
JR Z,M05AD ;
LD A,(IX+DATTYPE) ;/
CP $03 ;|jump if this is "CODE"
JR NZ,M05CA ;\
M05AD: POP HL ;
LD A,H ;/
OR L ;|jump if zero
JR NZ,M05B8 ;\
LD L,(IX+ARG1)
LD H,(IX+ARG1+1)
M05B8: PUSH HL
POP IX
LD A,(TADDR) ;/jump if VERIFY
CP $02 ;\
SCF ;force load
JR NZ,M05C4 ;
AND A ;force VERIFY
M05C4: LD A,$FF ;specify a data block
R_TAPE1: CALL R_TAPE ;/return if no tape loading error
RET C ;\
M05CA: RST $08 ;error TAPE LOADING ERROR
DEFB $1A ;
;******************************************************************
; Module: TAPE
; Routine: LOAD
; this routine does the nitty-gritty of actually loading and
; merging program text and merging data from tape - ugggg!!
;******************************************************************
LOAD:
M05CC: LD E,(IX+BLKLEN) ;/get the data block length
LD D,(IX+BLKLEN+1) ;\
PUSH HL ;save the length of the target data structure
LD A,H ;/
OR L ;|jump if it is not zero
JR NZ,M05DD ;\
INC DE ;/adjust to reserve space for a name and
INC DE ;| length bytes
INC DE ;\
EX DE,HL ;HL = requred block length, DE = 0
JR M05E9 ;
;handle an existing array with name the same name as the proposed array
M05DD: LD L,(IX+(-$06)) ;/get the other block length
LD H,(IX+(-$05)) ;\
EX DE,HL ;/
SCF ;|jump if the existing data block
SBC HL,DE ;| is at least long enough to hold
JR C,M0606 ;\ the new data
M05E9: LD DE,$0005 ;/add 5 bytes to the block length
ADD HL,DE ;|BC = number of additional bytes needed
LD B,H ;| for this data block
LD C,L ;\
; CALLBANKS CHK_SZ,HOMEROM,$00 ;check for BC bytes available
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,CHK_SZ ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
;
;if we got here then there is enough space for the data coming in
;
M0606: POP HL ;restore the existing data block length
LD A,(IX+DATTYPE) ;/
AND A ;|jump if this is a program
JR Z,M0673 ;\
LD A,H ;/jump if the existing block length is zero
OR L ;| to create the variable
JR Z,M0638 ;\
;
;destroy the present array with the name of the proposed data array
;
DEC HL ;point to the array size
LD B,(HL) ;/
DEC HL ;|get the array size into BC
LD C,(HL) ;|
DEC HL ;\
INC BC ;/add the length of the array name
INC BC ;| and array length bytes
INC BC ;\
LD (XPTR),IX ;save IX
; CALLBANKS DELREC,HOMEROM,$00 ;delete the existing array
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,DELREC ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
LD IX,(XPTR) ;restore IX
;
;
;
M0638: LD HL,(ELINE) ;/point to the $80 byte in the variables area
DEC HL ;\
LD C,(IX+BLKLEN) ;/get the required data block length
LD B,(IX+BLKLEN+1) ;\
PUSH BC ;save the block length
INC BC ;/
INC BC ;|need three more bytes for the array name and
INC BC ;\length
LD A,(IX+(-$03)) ;get the array ID for the incoming data
PUSH AF ;save it
; CALLBANKS INSERT,HOMEROM,$00 ;make room at (HL) for the array
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,INSERT ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
INC HL ;/
POP AF ;|store the array name
LD (HL),A ;\
POP DE ;/
INC HL ;|
LD (HL),E ;|store the array length
INC HL ;|
LD (HL),D ;\
INC HL ;point to the "number of dimensions"
PUSH HL ;/IX now points to the destination address for
POP IX ;\ the array data
SCF ;/"load..."
LD A,$FF ;|"...a data block"
JP R_TAPE1 ;\read the data block and exit via SLVM
;
;program loading
;
M0673: EX DE,HL ;DE = end address
LD HL,(ELINE) ;/point to the $80 byte at the end of the variables
DEC HL ;\ area
LD (XPTR),IX ;save the buffer header pointer
LD C,(IX+BLKLEN) ;/
LD B,(IX+BLKLEN+1) ;|get the data block length and briefly save it
PUSH BC ;\
; CALLBANKS DEL_DE,HOMEROM,$00 ;delete the bytes between HL and DE
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,DEL_DE ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
POP BC ;pop the block length
PUSH HL ;push the data buffer address
PUSH BC ;push the block length
;
; reserve space for the incoming lines
;
; CALLBANKS INSERT,HOMEROM,$00 ;make room at (HL) for BC bytes
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,INSERT ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
LD IX,(XPTR) ;get the buffer header pointer back
INC HL ;get the original address back
LD C,(IX+ARG2) ;/get the variables address from the file
LD B,(IX+ARG2+1) ;\
ADD HL,BC ;/point to the new variables area
LD (VARS),HL ;\ and save it in the system vars area
LD H,(IX+ARG1+1) ;get the putative line number
LD A,H ;/
AND $C0 ;|jump if not a valid line number
JR NZ,M06D5 ;\
LD L,(IX+ARG1) ;get the lower byte of the line number
LD (NEWPPC),HL ;store the line number into the next line number
LD (IY+ONSPPC),00 ;subline 0
M06D5: POP DE ;restore the block length
POP IX ;
SCF ;"load..."
LD A,$FF ;"...a data block"
LD HL,(PROG) ;get the address of the program text
DEC HL ;point to the $80 byte
LD (DATADD),HL ;data terminator character (no data)
JP R_TAPE1 ;read the tape
M06E5: LD C,(IX+BLKLEN) ;/get the required data block length
LD B,(IX+BLKLEN+1) ;\
PUSH BC ;save the block length
INC BC ;room for the $80 byte
; CALLBANKS ALLOCBC,HOMEROM,$00 ;expand the workspace BC bytes
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,ALLOCBC ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
LD (HL),$80 ;$80 byte for the end of the edit buffer
EX DE,HL ;HL = the start of the newly freed space
POP DE ;pop the block length
PUSH HL ;save the pointer to the end of the reserved area
PUSH HL ;...and again
POP IX ;point to the end of the reserved area
SCF ;/"load..."
LD A,$FF ;|"...a data block"
CALL R_TAPE1 ;\read the program lines in from tape
POP HL ;point to the newly loaded data
LD DE,(PROG) ;get the start of the program file
M0717: LD A,(HL) ;/get the first byte of the newly loaded BASIC progrm
AND $C0 ;|jump if not a valid line number
JR NZ,M0749 ;\
M071C: LD A,(DE) ;get the first byte of the old BASIC program
INC DE ;bump the old pointer
CP (HL) ;compare to the new BASIC
INC HL ;bump the new pointer
JR NZ,M0724 ;old and new line numbers not the same so jump
LD A,(DE) ;/compare the last half of the line numbers
CP (HL) ;\
M0724: DEC DE ;/bump both BASIC pointers back
DEC HL ;\
JR NC,M0744 ;jump if the new line number is less than or equal to the
; old line number to insert the new line into the program
PUSH HL ;save the new pointer
EX DE,HL ;HL=old pointer, DE=the new pointer
; CALLBANKS RECLEN,HOMEROM,$00 ;find the next variable or BASIC line
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,RECLEN ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
POP HL ;restore the new pointer
JR M071C ;back around to test the new line
M0744: CALL M0799 ;
JR M0717 ;
M0749: LD A,(HL) ;get the character from the new code
LD C,A ;/
CP $80 ;|return if we have reached the end of the code
RET Z ;\
;
;was not BASIC code, so try to find the entity in the variables area
; HL DE BC STK
PUSH HL ;save the pointer to the new code new old new
LD HL,(VARS) ;get the pointer to the variables area vars old new
M0752: LD A,(HL) ;/
CP $80 ;|jump if there are no variables
JR Z,M0790 ;\
CP C ;/jump if the variable name in the new code starts with
JR Z,M0776 ;\ the same letter as the one just found
M075A: PUSH BC ;save C vars old BC,new
; CALLBANKS RECLEN,HOMEROM,$00 ;find the next variable or BASIC line
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,RECLEN ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
; vars newrec new
POP BC ;restore C
EX DE,HL ;/put pointers back and try the next variable name vars newrec
JR M0752 ;\
M0776: AND $E0 ;mask out the variable discriminator bits
CP $A0 ;/jump if not a multi letter variable
JR NZ,M078E ;\
;
;loop through the characters of a multi-letter variable name to determine whether the new
; name matches the one in the variables area
;
POP DE ;get the pointer to the new code vars new
PUSH DE ;save it again vars new new
PUSH HL ;save the pointer to the old code vars new vars,new
M077F: INC HL ;/move to the next character
INC DE ;\
LD A,(DE) ;/
CP (HL) ;|jump if the variable names do not match
JR NZ,M078B ;\
RLA ;/loop back around if not the last character
JR NC,M077F ;\
POP HL ;restore the pointer to the old code vars new new
JR M078E ;
M078B: POP HL ;/multi-letter name did not match, so vars new new
JR M075A ;\ back around to try again
M078E: LD A,$FF ;will force falling through at M0799
M0790: POP DE ;restore the pointer to the new code vars new --
EX DE,HL ;swap the pointers new vars
INC A ;
SCF ;
CALL M0799 ;
JR M0749 ;
M0799: JR NZ,M07CF ;jump if we are just inserting a record
EX AF,AF' ;
LD (XPTR),HL ;save
EX DE,HL ; vars new
;find the next line or variable, then delete it
; CALLBANKD RECLEN,HOMEROM,$00,DELREC,HOMEROM,$00
;CALLBANKD: MACRO CALLADR1,DESTBANK1,HORIZSEL1,CALLADR2,DESTBANK2,HORIZSEL2
PUSH IX
EXX
LD HL,RECLEN ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
EXX
LD HL,DELREC ;
PUSH HL ;
LD L,$00 ;
LD H,HOMEROM ;
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
EX DE,HL ;
LD HL,(XPTR) ;
EX AF,AF' ;
;insert a new record
M07CF: EX AF,AF' ;
PUSH DE ;save the pointer to the new code
; CALLBANKS RECLEN,HOMEROM,$00 ;find the next variable or program line
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,RECLEN ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
LD (XPTR),HL ;save pointer to old code
LD HL,(PROG) ;get the pointer to the BASIC program
EX (SP),HL ;
PUSH BC ;
EX AF,AF' ;
JR C,M080E ;
DEC HL ;
; CALLBANKS INSERT,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,INSERT ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
INC HL ;
JR M0825 ;
M080E:
;M080E: CALLBANKS INSERT,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,INSERT ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
M0825: INC HL ;
POP BC ;
POP DE ;
LD (PROG),DE ;
LD DE,(XPTR) ;
PUSH BC ;
PUSH DE ;
EX DE,HL ;
LDIR ;
POP HL ;
POP BC ;
PUSH DE ;
; CALLBANKS DELREC,HOMEROM,$00
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,DELREC ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
POP DE ;
RET ;
;******************************************************************
; Module: TAPE
; Routine: SAVE
;******************************************************************
;select the keyboard and lower screen as the current channel
SAVE:
M0851: PUSH HL ;save the data buffer address
LD A,$FD ;channel -3, keyboard and lower screen
; CALLBANKS SELECT,HOMEROM,$00 ;select channel -3
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,SELECT ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
XOR A ;message number 0
LD DE,$3C89 ;
; CALLBANKS PUTMES,HOMEROM,$00 ;put message 0 to current channel
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,PUTMES ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
SET CLHS,(IY+OTVFLAG) ;force clear lower half screen if keypressed
CALL M08AA ;wait for a key to be pressed
PUSH IX ;save the header buffer address
LD DE,$0011 ;tape header length
XOR A ;tell W_TAPE we want to write a header
CALL W_TAPE ;
POP IX ;restore the header buffer address
LD B,$32 ;/
M089A: HALT ;|wait for approx 1000mS
DJNZ M089A ;\
LD E,(IX+BLKLEN) ;get the length of the data block from the
LD D,(IX+BLKLEN+1) ; header
LD A,$FF ;tell W_TAPE we are writing data
POP IX ;pop the data buffer address
JP W_TAPE ;write the data and return to
; caller via W_TAPE's return
;******************************************************************
; Module: TAPE
; Routine: AKEY
;******************************************************************
AKEY:
M08AA: PUSH AF ;/
PUSH BC ;|briefly save registers
PUSH DE ;\
LD BC,$9C40 ;/
M08B0: DEC BC ;|wait for approx 238mS
LD A,C ;|
OR B ;|
JR NZ,M08B0 ;\
;wait for a key press
M08B5: XOR A ;zero the accum
IN A,($FE) ;poll the keyboard
AND $1F ;use only the keyboard bits
CP $1F ;/jump if no key is pressed
JR Z,M08B5 ;\
; CALLBANKS CLLHS,HOMEROM,$00 ;clear the lower half of the screen
;CALLBANKS: MACRO CALLADR,DESTBANK,HORIZSEL
PUSH IX
EXX
LD HL,CLLHS ;
PUSH HL ;
LD L,$00 ;horizontal select
LD H,HOMEROM ;home bank
PUSH HL ;
LD HL,$0000 ;
PUSH HL ;
PUSH HL ;
EXX ;
CALL M0F99 ;CALL BANK
POP IX
; ENDM
POP DE ;/
POP BC ;|restore registers
POP AF ;\
RET ;back to the "save" routine
BADBAS:
M08D9: EXX ;alt regs
LD HL,$1BED ;address for BAD BASIC COMMAND
; error routine
PUSH HL ;save jump address
LD L,$00 ;all chunks
LD H,$FF ;home bank
PUSH HL ;save bank/chunk
EXX ;reg registers
CALL GOTO_B ;local local GOTO_BANK
;******************************************************************
; Module: INIT
; Routine: EXTINIT
;******************************************************************
EXTINIT:
LD HL,$5EEA ;/initialize the SYSCON
LD (SYSCON),HL ;\system variable
CALL BLDSCT ;build the system config table
LD HL,(SYSCON) ;point to SYSCON table
LD DE,$0008 ;/point to LROS ID
ADD HL,DE ;\
LD A,(HL) ;/
CP $01 ;|jump if not LROS
JR NZ,M090F ;\
PUSH HL ;save LROS pointer
CALL NORMSVAR ;initialize various system variables
POP HL ;/
INC HL ;|
LD E,(HL) ;|push LROS entry point
INC HL ;|
LD D,(HL) ;|
PUSH DE ;\
LD B,$00 ;specify dock bank
INC HL ;/
LD C,(HL) ;|get HSR byte
PUSH BC ;\
EI ;enable interrupts
CALL $5200+GOTO_BANK ;call GOTO_BANK - goto the AROS
M090F: LD HL,(SYSCON) ;get SYSCON
INC HL ;/get possible LROS ID
LD A,(HL) ;\
CP $02 ;/jump if AROS machine code
JR Z,M091E ;\ cartridge
CALL NORMSVAR ;initialize various system variables
JP M099A ;handle
M091E: DEC HL ;/get the code type designator
LD A,(HL) ;\
CP $01 ;/jump if BASIC code
JR Z,M0956 ;\
CP $02 ;/jump if machine code
JR NZ,LROS_ERR ;\
LD DE,$0006 ;/
ADD HL,DE ;|
LD C,(HL) ;|BC contains the number of
INC HL ;| bytes to reserve for machine code
LD B,(HL) ;\
LD HL,$6840 ;start of LROS code buffer?
ADD HL,BC ;/
EX DE,HL ;|move BC bytes at (HL) up to (DE)
LD HL,$6840 ;| where (DE) = $6840+BC
LDIR ;\
CALL INITSYSVAR ;
LD HL,(SYSCON) ;/
LD DE,$0005 ;|get the AROS memory specification
ADD HL,DE ;|
LD A,(HL) ;\
CP $00 ;/jump if not autostart
JR Z,M099A ;\
DEC HL ;/C = chunk specification
LD C,(HL) ;\
DEC HL ;/
LD D,(HL) ;|DE = address of first BASIC line
DEC HL ;| or first machine code instruction
LD E,(HL) ;\
PUSH DE ;save the start address
LD B,$00 ;/save the chunk specification
PUSH BC ;\
EI ;enable interrupts
CALL $5200+GOTO_BANK ;GOTO BANK (jump to the machine code)
M0956: CALL NORMSVAR ;
LD A,$80 ;/set flag to show AROS is present
LD (ARSFLG),A ;\
LD HL,AROS ;/jump to the AROS handler
PUSH HL ;\
LD B,$FF ;home bank
LD C,$00 ;all of memory
PUSH BC ;
CALL $5200+GOTO_BANK ;GOTO BANK
LROS_ERR: RST $08 ;/error "MISSING LROS"
DEFB $1B ;\
NORMSVAR: LD HL,$6840 ;point past the RAM resident services
LD DE,$0015 ;/reserve space for the CHANS table
ADD HL,DE ;\
INITSYSVAR: LD (DATADD),HL ;initialize the DATA pointer
INC HL ;/point to the start of BASIC
LD (PROG),HL ;\
LD (VARS),HL ;initialize the variables pointer
LD (HL),$80 ;/drop the sentinal at the end of the
;\ variables ares
INC HL ;/initialize the input line buffer
LD (ELINE),HL ;\
LD (HL),$0D ;stuff a carriage return
INC HL ;/sentinal byte
LD (HL),$80 ;\
INC HL ;/
LD (WORKSP),HL ;|initialize system variables
LD (STKBOT),HL ;|
LD (STKEND),HL ;\
XOR A ;
LD (ARSFLG),A ;show no AROS present
LD (VIDMOD),A ;normal video mode
RET ;
M099A: LD D,$FF ;home bank
LD E,$80 ;HS select, top chunk in EXROM/DOCK
LD HL,LED18 ;jump address in HOME ROM
PUSH HL ;stack the jump address
PUSH DE ;stack bank/HS
LD HL,(SYSCON) ;/point to the first expansion bank
LD DE,$000C ;| entry
ADD HL,DE ;\
LD B,$00 ;prep BC for the next ops
M09AC: LD A,(HL) ;get the entry for an expansion bank
CP $80 ;/jump if at the end of the SYSCON area
JR Z,M09E3 ;\
CP $00 ;/no entry for this bank, so move on
JR Z,M09DD ;\to check the next one
INC HL ;/pick up bank number
LD B,(HL) ;\
LD DE,$0014 ;/
ADD HL,DE ;|
LD A,(HL) ;|jump if active? or code?
RRCA ;|
JR C,M09C4 ;\
INC HL ;/point to the next exp bank entry in
INC HL ;|the SYSCON area
INC HL ;\
JR M09AC ;back around to check for more
M09C4: INC HL ;/get HS for this exp bank
LD A,(HL) ;\
POP DE ;remove the bank/HS from the stack
CP E ;/jump if this exp bank needs more
JR C,M09CF ;\ HS than is currently allocated
PUSH DE ;save bank/HS
INC HL ;/point to the next exp bank
INC HL ;|entry in the SYSCON
JR M09AC ;\
M09CF: POP DE ;trash the call address
LD DE,$0005 ;/point to CAL nn or JP nn
SBC HL,DE ;| in SYSCON table and
PUSH HL ;\ stack it
LD C,A ;update HS
PUSH BC ;save bank/HS
INC DE ;/
INC DE ;|point to next entry in SYSCON
ADD HL,DE ;\
JR M09AC ;back around for more
M09DD: LD DE,$0018 ;/point to the next expansion bank entry
ADD HL,DE ;\in the SYSCON area
JR M09AC ;back around to check for more
M09E3: POP BC ;get the bank/HS
LD A,B ;/
CP $FF ;|jump if going to HOME bank
JR Z,M09ED ;\
LD C,$58 ;allow chunks 3, 4, and 6 to be in expansion banks
JR M09EF ;
M09ED: LD C,$00 ;allocate all chunks to HOME
M09EF: PUSH BC ;save bank/HS
EI ;enable interrupts
CALL $5200+GOTO_BANK ;goto bank
;******************************************************************
; Module: INIT
; Routine: BLDSCT
; build the system configuration table
;******************************************************************
BLDSCT:
LD HL,(SYSCON) ;point to SYSCON buffer
XOR A ;0 A
LD (MAXBNK),A ;zero out MAXBANK
LD ($6315),A ;zero out dispatcher's copy of MAXBANK
LD DE,$0008 ;/point to LROS buffer
ADD HL,DE ;\
;
;transfer bytes from LROS to the SYSCON table
;
LD E,$FF ;/dest bank = $FF (home)
LD D,$00 ;|src bank = $00 (dock)
PUSH DE ;\
LD DE,$0001 ;/set source address
PUSH DE ;\
PUSH HL ;set destination address
LD DE,$0004 ;/set length
PUSH DE ;\
LD DE,$0001 ;/set direction (LDIR)
PUSH DE ;\
CALL $5200+XFER_BYTES ;transfer the bytes
LD A,(HL) ;/
CP $01 ;|jump if LROS signature present
JR Z,M0A3E ;\
LD (HL),$00 ;zero LROS signature to prevent
; system from incorrectly seeing
; an LROS as present
;
;transfer bytes from AROS to the SYSCON
;
LD E,$FF ;/dest bank = $FF (home)
LD D,$00 ;|src bank = $00 (dock)
PUSH DE ;\
LD DE,$8000 ;/set source address
PUSH DE ;\
LD HL,(SYSCON) ;/get SYSCON buffer address
PUSH HL ;\and use as destination address
LD DE,$0008 ;/set length
PUSH DE ;\
LD DE,$0001 ;/set direction
PUSH DE ;\
CALL $5200+XFER_BYTES ;transfer the bytes
INC HL ;/get AROS signature byte
LD A,(HL) ;\
CP $02 ;/jump if valid AROS ID byte
JR Z,M0A3E ;\
LD (HL),$00 ;zero out AROS ID byte, as we do not have
; a valid AROS cartridge
;we will also get to this point if there is a valid LROS via $0A1A
M0A3E: LD HL,(SYSCON) ;get SYSCON buffer address
LD DE,$000D ;/point to AROS buffer?
ADD HL,DE ;\
LD D,$C0 ;bank status register address
LD E,$00 ;bank status register value
CALL $5200+WRITE_BS_REG ;write to bank status register
M0A4C: CALL M0BD1 ;find valid banks
JP NC,M0AD4 ;
LD B,A ;
SET 7,B ;
LD (HL),B ;
RES 7,B ;
INC HL ;
LD C,$FE ;/dest bank = EXROM
PUSH BC ;\
LD DE,$08E7 ;/set source address
PUSH DE ;\
LD DE,$0000 ;/get SYSCON buffer address
PUSH DE ;\and use as destination address
LD DE,$0001 ;/set length
PUSH DE ;\
PUSH DE ;set direction
CALL $5200+XFER_BYTES ;transfer the bytes
LD E,$FF ;dest bank = $FF (home)
LD D,A ;src bank provided by caller
PUSH DE ;set bank
LD DE,$0000 ;/set source adr
PUSH DE ;\
PUSH HL ;set dest address
LD DE,$0016 ;/set length
PUSH DE ;\
LD DE,$0001 ;/set direction
PUSH DE ;\
CALL $5200+XFER_BYTES ;transfer the bytes
LD D,(HL) ;/
LD A,($08E7) ;|jump if we are not in
CP D ;|the EXTROM
JP NZ,M0AC2 ;\
LD C,$FE ;dest bank = $FE (external)
PUSH BC ;set banks
LD DE,$0A4C ;/set source adr
PUSH DE ;\
LD DE,$0000 ;/set dest adr
PUSH DE ;\
LD DE,$0001 ;length/direction
PUSH DE ;set length
PUSH DE ;set direction
CALL $5200+XFER_BYTES ;get bytes
LD E,$FF ;dest bank = home
LD D,A ;src bank = user's
PUSH DE ;set banks
LD DE,$0000 ;/set source adr
PUSH DE ;\
PUSH HL ;set user's destination
LD DE,$0016 ;/set block length
PUSH DE ;\
LD DE,$0001 ;/set direction
PUSH DE ;\
CALL $5200+XFER_BYTES ;transfer the bytes
LD D,(HL) ;/
LD A,($08E7) ;|get first byte of user's buffer
CP D ;|and jump if user is not EXROM
JP NZ,M0AC2 ;\
DEC HL ;
DEC HL ;
CALL M0ADB ;
LD DE,$0015 ;
ADD HL,DE ;
JR M0ACA ;
M0AC2: LD A,D ;
AND $DF ;
LD (HL),A ;
DEC HL ;
CALL M0C1F ;
M0ACA: LD D,$C0 ;
LD E,$01 ;
CALL $5200+WRITE_BS_REG ;
JP M0A4C ;
M0AD4: DEC HL ;
LD (HL),$80 ;
CALL M0CFB ;
RET ;
M0ADB: LD (HL),$02 ;
PUSH BC ;push user's bank info
LD DE,$0038 ;/set source
PUSH DE ;\
PUSH DE ;set destination
LD DE,$0010 ;/set block length
PUSH DE ;\
LD DE,$0001 ;/set direction
PUSH DE ;\
CALL $5200+XFER_BYTES ;transfer bytes
INC HL ;
INC HL ;
LD A,(HL) ;
SET 0,A ;
LD (HL),A ;
LD DE,$0000 ;
LD A,$01 ;
M0AF9: EX AF,AF' ;
PUSH HL ;
EX DE,HL ;
LD DE,$2000 ;
ADD HL,DE ;
EX DE,HL ;
POP HL ;
LD B,$FE ;src bank = EXROM
LD A,(MAXBNK) ;get MAXBANK
LD C,A ;dest bank = MAXBANK
PUSH BC ;set banks
LD BC,$08E7 ;/set source
PUSH BC ;\
PUSH DE ;set destination
LD BC,$0001 ;/
PUSH BC ;|set byte count and direction
PUSH BC ;\
CALL $5200+XFER_BYTES ;transfer bytes
LD A,(MAXBNK) ;get MAXBANK
LD B,A ;src = MAXBANK
LD C,$00 ;dest = Dock
PUSH BC ;set banks
PUSH DE ;set user's source
INC HL ;bump user's destination
PUSH HL ;set user's destination
LD BC,$0001 ;/
PUSH BC ;|set block length and direction
PUSH BC ;\
CALL $5200+XFER_BYTES ;transfer bytes
LD B,(HL) ;/
DEC HL ;|jump if destination was
LD A,($08E7) ;|not EXROM
CP B ;|
JR NZ,M0B95 ;\
LD B,$FE ;src bank = EXROM
LD A,(MAXBNK) ;get MAXBANK
LD C,A ;dest bank = MAXBANK
PUSH BC ;set banks
LD BC,$0A4C ;/set source
PUSH BC ;\
PUSH DE ;set user's destination
LD BC,$0001 ;/
PUSH BC ;|set direction and byte count
PUSH BC ;\
CALL $5200+XFER_BYTES ;transfer bytes
LD A,(MAXBNK) ;get MAXBANK
LD B,A ;src bank = MAXBANK
LD C,$00 ;dest bank = Dock
PUSH BC ;set banks
PUSH DE ;set user's source
INC HL ;bump user's destination
PUSH HL ;set user's destination
LD BC,$0001 ;/
PUSH BC ;|set direction and byte count
PUSH BC ;\
CALL $5200+XFER_BYTES ;transfer bytes
LD B,(HL) ;get the value at (HL)
DEC HL ;back a byte
LD A,($0A4C) ;A=$CD???
CP B ;/jump if B is not $CD
JR NZ,M0B95 ;\
;
;this routine sets the bit whose number is in A'
;
EX AF,AF' ;
LD B,(HL) ;get the byte at (HL)
CP $01 ;/
JR NZ,M0B68 ;|if 1, set bit 1 in B
SET 1,B ;| then move on
JR M0B92 ;\
M0B68: CP $02 ;/
JR NZ,M0B70 ;|if 2, set bit 2 in B
SET 2,B ;| then move on
JR M0B92 ;\
M0B70: CP $03 ;/
JR NZ,M0B78 ;|if 3, set bit 3 in B
SET 3,B ;| then move on
JR M0B92 ;\
M0B78: CP $04 ;/
JR NZ,M0B80 ;|if 4, set bit 4 in B
SET 4,B ;| then move on
JR M0B92 ;\
M0B80: CP $05 ;/
JR NZ,M0B88 ;|if 5, set bit 5 in B
SET 5,B ;| then move on
JR M0B92 ;\
M0B88: CP $06 ;/
JR NZ,M0B90 ;|if 6, set bit 6 in B
SET 6,B ;| then move on
JR M0B92 ;\
M0B90: SET 7,B ;else set bit 7
M0B92: LD (HL),B ;save byte back
JR M0BCA ;
;
;this routine resets the bit whose number is in A'
;
M0B95: EX AF,AF' ;
LD B,(HL) ;
CP $01 ;/
JR NZ,M0B9F ;|if 1, reset bit 1 in B
RES 1,B ;| then move on
JR M0BC9 ;\
M0B9F: CP $02 ;/
JR NZ,M0BA7 ;|if 2, reset bit 2 in B
RES 2,B ;| then move on
JR M0BC9 ;\
M0BA7: CP $03 ;/
JR NZ,M0BAF ;|if 3, reset bit 3 in B
RES 3,B ;| then move on
JR M0BC9 ;\
M0BAF: CP $04 ;/
JR NZ,M0BB7 ;|if 4, reset bit 4 in B
RES 4,B ;| then move on
JR M0BC9 ;\
M0BB7: CP $05 ;/
JR NZ,M0BBF ;|if 5, reset bit 5 in B
RES 5,B ;| then move on
JR M0BC9 ;\
M0BBF: CP $06 ;/
JR NZ,M0BC7 ;|if 6, reset bit 6 in B
RES 6,B ;| then move on
JR M0BC9 ;\
M0BC7: RES 7,B ;else reset bit 7
M0BC9: LD (HL),B ;save byte back
M0BCA: INC A ;
CP $08 ;
JP NZ,M0AF9 ;
RET ;
;
;find all used banks in the machine
;
M0BD1: LD A,(MAXBNK) ;get MAXBANK
INC A ;bump it
LD (MAXBNK),A ;save new MAXBANK
LD ($6315),A ;save dispatcher's
; local copy of MAXBANK
LD D,$A0 ;/
LD E,A ;|write to bank status register
CALL $5200+WRITE_BS_REG ;\
;
;check expansion banks?
;
LD D,$80 ;/
LD E,A ;|write to bank status register
CALL $5200+WRITE_BS_REG ;\
LD D,$40 ;/
LD E,$00 ;|write to bank status register
CALL $5200+WRITE_BS_REG ;\
PUSH AF ;save AF briefly
LD A,($A000) ;/save value at $A0000
EX AF,AF' ;\
LD A,$04 ;/store 4 into chunk 5 BSR
LD ($A000),A ;\
LD D,$A0 ;/
LD E,$C0 ;|read bank status register
CALL $5200+READ_BS_REG ;\
BIT 2,E ;/jump if 4 was successfully written
JR NZ,M0C0A ;(0C0A);\
EX AF,AF' ;/restore the value at $A000
LD ($A000),A ;\
POP AF ;restore AF
SCF ;set error flag
RET ;done
M0C0A: EX AF,AF' ;/restore the value at $A000
LD ($A000),A ;\
POP AF ;restore A
DEC A ;
LD (MAXBNK),A ;save new MAXBANK
LD ($6315),A ;save dispatcher's
; local copy of MAXBANK
LD D,$C0 ;/
LD E,$04 ;|write to bank status register
CALL $5200+WRITE_BS_REG ;\
AND A ;
RET ;
M0C1F: DEC HL ;
LD (HL),$01 ;
LD DE,$0015 ;
ADD HL,DE ;
LD A,(HL) ;
RRA ;
JR C,M0C2F ;(0C2F) ;
LD DE,$0004 ;
ADD HL,DE ;
RET ;
M0C2F: LD C,$08 ;
LD A,(MAXBNK) ;
DEC HL ;
DEC HL ;
DEC HL ;
LD D,(HL) ;
DEC HL ;
LD E,(HL) ;
LD H,D ;
LD L,E ;
LD B,A ;
PUSH HL ;
PUSH BC ;
LD BC,$0000 ;
PUSH BC ;
PUSH BC ;
CALL $5200+CALL_BANK ;
LD DE,$0008 ;
ADD HL,DE ;
RET ;
;******************************************************************
; Module: INIT
; Routine: RESSCT
;******************************************************************
XOR A
LD (MAXBNK),A
LD ($6315),A
LD D,$C0
LD E,$00
CALL $5200+WRITE_BS_REG
LD HL,(SYSCON)
LD DE,$000C
M0C60: ADD HL,DE
CALL M0BD1
JP NC,M0CF5
LD A,(HL)
PUSH HL
CP $80
JR NZ,M0C72 ;(0C72)
LD DE,$0018
ADD HL,DE
LD (HL),A
M0C72: CALL M0BD1
LD HL,$5FE9
LD E,$FF
LD D,A
PUSH DE
LD DE,$0000
PUSH DE
PUSH HL
LD DE,$0016
PUSH DE
LD DE,$0001
PUSH DE
CALL $5200+XFER_BYTES
EX AF,AF'
LD A,(HL)
CPL
DEC HL
LD (HL),A
EX AF,AF'
LD D,$FF
LD E,A
PUSH DE
PUSH HL
LD DE,$0002
PUSH DE
LD DE,$0001
PUSH DE
PUSH DE
CALL $5200+XFER_BYTES
LD E,$FF
LD D,A
PUSH DE
LD DE,$0002
PUSH DE
INC HL
PUSH HL
LD DE,$0001
PUSH DE
PUSH DE
CALL $5200+XFER_BYTES
LD A,(HL)
DEC HL
LD B,(HL)
CP B
JR NZ,M0CCA ;(0CCA)
POP HL
LD A,(HL)
CP $02
JR NZ,M0CC5 ;(0CC5)
INC HL
INC HL
JR M0CE8 ;(0CE8)
M0CC5: CALL M0ADB
JR M0CE8 ;(0CE8)
M0CCA: LD C,(HL)
POP HL
INC HL
INC HL
LD A,(HL)
CP C
JR Z,M0CE8 ;(0CE8)
PUSH HL
EX DE,HL
LD HL,$5FE9
LD BC,$0016
LDIR
POP HL
DEC HL
LD A,(MAXBNK)
SET 7,A
LD (HL),A
CALL M0C1F
INC HL
M0CE8: LD D,$C0
LD E,$01
CALL $5200+WRITE_BS_REG
LD DE,$0016
JP M0C60
M0CF5: LD (HL),$80
CALL M0CFB
RET
M0CFB: XOR A ;/load 0 into MAXBANK
LD (MAXBNK),A ;\
M0CFF: LD HL,(SYSCON) ;get SYSCON buffer address
LD DE,$000C ;
ADD HL,DE ;
M0D06: LD A,(HL) ;
CP $80 ;
JR Z,M0D84 ;(0D84)
INC HL
LD A,(HL)
BIT 7,A
JR NZ,M0D17 ;(0D17)
LD DE,$0017
ADD HL,DE
JR M0D06 ;(0D06)
M0D17: LD ($5FE9),HL
DEC HL
LD A,(HL)
CP $02
JR NZ,M0D28 ;(0D28)
LD DE,$0017
ADD HL,DE
LD A,$FF
JR M0D2D ;(0D2D)
M0D28: LD DE,$0017
ADD HL,DE
LD A,(HL)
M0D2D: LD ($5FEB),A
M0D30: INC HL
M0D31: LD A,(HL)
CP $80
JR Z,M0D64 ;(0D64)
INC HL
LD A,(HL)
BIT 7,A
JR NZ,M0D42 ;(0D42)
LD DE,$0017
ADD HL,DE
JR M0D30 ;(0D30)
M0D42: DEC HL
LD A,(HL)
CP $02
JR NZ,M0D4E ;(0D4E)
LD DE,$0017
ADD HL,DE
JR M0D30 ;(0D30)
M0D4E: EX DE,HL
LD BC,$0017
ADD HL,BC
LD A,($5FEB)
LD B,A
LD A,(HL)
CP B
JR NC,M0D30 ;(0D30)
LD ($5FEB),A
LD ($5FE9),DE
JR M0D30 ;(0D30)
M0D64: LD A,(MAXBNK)
INC A
LD (MAXBNK),A
LD HL,($5FE9)
LD (HL),A
LD E,$FF
LD D,A
PUSH DE
LD E,(HL)
LD D,$00
PUSH DE
LD E,$00
PUSH DE
LD E,$01
PUSH DE
PUSH DE
CALL $5200+XFER_BYTES
JP M0CFF
M0D84: XOR A
LD (MAXBNK),A
LD ($6315),A
LD D,$C0
LD E,$00
CALL $5200+WRITE_BS_REG
LD HL,(SYSCON)
LD DE,$000D
ADD HL,DE
LD D,$A0
M0D9B: CALL M0BD1
RET NC
LD E,(HL)
CALL $5200+WRITE_BS_REG
LD D,$C0
LD E,$01
CALL $5200+WRITE_BS_REG
LD DE,$0018
ADD HL,DE
JR M0D9B ;(0D9B)
;******************************************************************
; Module: CHG_VID
; Routine: OPDFIL
; open the second display file. move the UDG then move the stack
; and RAM resident code to high memory. update the video mode and
; the video port.
;******************************************************************
OPDFIL:
M0DB0: PUSH BC ;/
PUSH DE ;|save caller's
PUSH HL ;|registers
PUSH AF ;\
LD HL,(PRAMT) ;get physical ramtop
LD DE,(UDG) ;get the pointer to the UDG
AND A ;/number of bytes occupied by
SBC HL,DE ;\the UDG
LD B,H ;/put into byte counter
LD C,L ;\
INC BC ;adjust for zero base
LD HL,(UDG) ;point to the present UDG
PUSH HL ;brefly save
LD DE,$0840 ;number of bytes needed by
; RAM resident routines and
; stack
AND A ;/compute the new address
SBC HL,DE ;| for the UDG
EX DE,HL ;\
POP HL ;restore the present UDG address
LD (UDG),DE ;point to the new UDG location
LDIR ;move the UDG
LD HL,$0000 ;/HL will contain the new
ADD HL,SP ;|SP used when the stack and
LD BC,$97C0 ;|RAM resident code are moved
ADD HL,BC ;\
DI ;interrupts now will be really,
; really bad!
LD SP,HL ;update the stack pointer
LD DE,$F7C0 ;new location for stack and RAM routines
LD HL,$6000 ;old location
LD BC,$0840 ;length of stuff to move
LDIR ;move it
LD HL,$1D00 ;point to the fix table
LD BC,$97C0 ;offset to be added to addresses
M0DEE: LD E,(HL) ;/
INC HL ;|get fix address
LD D,(HL) ;\
INC HL ;point to next entry
LD A,E ;/jump if we have reached the end
OR D ;|of the table
JR Z,M0E05 ;\
EX DE,HL ;/point to moved code that
ADD HL,BC ;\needs fixing
PUSH DE ;save the table pointer
LD E,(HL) ;/
INC HL ;|get the code needing fixing
LD D,(HL) ;\
EX DE,HL ;/
ADD HL,BC ;|
EX DE,HL ;|fix the address and
LD (HL),D ;|put it back
DEC HL ;|
LD (HL),E ;\
POP HL ;restore the table pointer
JR M0DEE ;back around for more entries
M0E05: POP AF ;/get caller's desired video mode
LD (VIDMOD),A ;\and store it
PUSH AF ;save it again
EI ;interrupts are OK again
;clear the newly opend second display file
LD HL,$6000 ;point to the second display file
M0E0E: XOR A ;zero the accum
LD (HL),A ;zero a byte
INC HL ;point to the next
LD A,H ;/zero until we reach $7AFF
CP $7B ;\
JR NZ,M0E0E ;not done yet
POP AF ;get the requested video mode
PUSH AF ;save it again
AND $7F ;only use the lower seven bits
; (don't munge the EXROM select)
LD B,A ;save it in B
IN A,($FF) ;get the present value of the
; video select port
AND $80 ;save the EXROM select
OR B ;OR in the request
OUT ($FF),A ;update the port
POP HL ;/
POP DE ;|restore caller's
POP BC ;|registers
POP AF ;\
RET ;
;******************************************************************
; Module: CHG_VID
; Routine: CLDFIL
; close the second display file
; moves the stack and RAM resident code from high memory back to
; low memory. updates SP and relocates the UDG.
;******************************************************************
CLDFIL:
M0E27: PUSH AF ;/
PUSH BC ;|save caller's registers
PUSH DE ;|
PUSH HL ;\
IN A,($FF) ;/get display mode port value
AND $80 ;|and set for black and white,
OUT ($FF),A ;\normal video,EXROM selected
LD HL,$0000 ;/
ADD HL,SP ;|set HL to the value the
LD DE,$97C0 ;|SP will need once the stack
AND A ;|has been moved to low memory
SBC HL,DE ;\
DI ;we can't be interruped or we
; will be in a real mess!
LD SP,HL ;update the stack pointer
LD HL,$FFFF ;/move the RAM resident code
LD DE,$683F ;|and the stack back to low
LD BC,$0840 ;|memory (starting at $6000)
LDDR ;\
LD HL,$1D00 ;the location of the fix table
LD BC,$97C0 ;offset value to convert code addresses
; from high memory addresses to
; low memory addresses
M0E4E: LD E,(HL) ;/
INC HL ;|get a fix address
LD D,(HL) ;\
INC HL ;point to the next one
LD A,E ;/
OR D ;|jump if the end of the table
JR Z,M0E66 ;\
PUSH HL ;save the table pointer
EX DE,HL ;/
LD E,(HL) ;|get the JP/CALL address
INC HL ;|in the RAM resident code
LD D,(HL) ;\
EX DE,HL ;/convert the address from
AND A ;|high memory to low memory
SBC HL,BC ;\
EX DE,HL ;/
LD (HL),D ;|modify the code
DEC HL ;|
LD (HL),E ;\
POP HL ;restore the table pointer
JR M0E4E ;back around for more entries
M0E66: XOR A ;/force normal video mode
LD (VIDMOD),A ;\
EI ;we can now allow interrupts again
LD HL,$F7BF ;address of UDG end when code is in
; high memory
LD DE,$FFFF ;new UDG location
PUSH HL ;save the old UDG address
LD BC,(UDG) ;get the current UDG pointer
AND A ;/number of bytes to move
SBC HL,BC ;\
LD B,H ;/transfer to byte counter
LD C,L ;\
INC BC ;bump by one
POP HL ;restore old address
LDDR ;move the UDG
LD DE,$0840 ;/
LD HL,(UDG) ;|update the UDG pointer
ADD HL,DE ;|in the system variables
LD (UDG),HL ;\
POP HL ;/
POP DE ;|restore the caller's
POP BC ;|registers
POP AF ;\
RET ;
;******************************************************************
; Module: CHG_VID
; Routine: CHG_V
; change the 2068 video mode
; Entry: requested video mode in A
;******************************************************************
CHG_V:
PUSH BC ;/
PUSH DE ;|save caller's registers
PUSH HL ;|
PUSH AF ;\
LD B,A ;save requester's mode
LD A,(VIDMOD) ;/jump if present mode is NOT
AND A ;|zero
JR NZ,M0EED ;\
OR B ;/jump if mode '0' is requested
JP Z ,M0F3D ;|and current mode is '0'. exit video mode change
;\with out doing anything
;intitiate a change from mode '0' to some other mode
LD HL,$12C0 ;number of bytes needed for RAM services
LD B,H ;/save for REMGSZ later on, if needed
LD C,L ;\
LD DE,$0840 ;/$2B00 total bytes needed
ADD HL,DE ;\
LD DE,(STKEND) ;/add to free RAM space stored in
ADD HL,DE ;\STKEND
;possible error in memory check. the technical manual mentions that
; overflow is not checked
LD DE,(RAMTOP) ;/
AND A ;|if the carry is set, RAMTOP is set
SBC HL,DE ;\too low to allow moving the RAM services
JP NC,M0F3A ;error exit
;adjust system variable address pointers
LD HL,$683F ;fence value: all system variables
; that point above this will be
; changed.
; (BC was set up earlier to $12C0)
LD DE,REMGSZ ;/address for REMGSZ
PUSH DE ;\
LD DE,$FF00 ;/specify home bank, all chunks
PUSH DE ;\ in home
LD DE,$0000 ;/
PUSH DE ;|no parameters in or out
PUSH DE ;\
CALL $5200+CALL_BANK ;CALL_BANK (REMGSZ)
LD HL,(STKEND) ;/
EX DE,HL ;|move the fp stack
LDDR ;\
POP AF ;/restore caller's video mode
PUSH AF ;\
CALL OPDFIL ;open the second display file
LD BC,$97C0 ;/
LD HL,(ERRSP) ;|point the ERRSP to the newly moved
ADD HL,BC ;|stack
LD (ERRSP),HL ;\
LD HL,(LISTSP) ;/
ADD HL,BC ;|update list stack pointer
LD (LISTSP),HL ;\
LD HL,(MSTBOT) ;/
ADD HL,BC ;|update machine stack pointer
LD (MSTBOT),HL ;\
JR M0F3D ;jump to exit
M0EED: LD A,B ;/jump if requested mode is
AND A ;|'0' (move the stack and
JR Z,M0F01 ;\RAM resident code back down)
;the requested mode was NOT zero and the present mode is not zero, so
; simply update the necessary items, then exit
AND $7F ;don't allow changes to the EXROM
; select
LD B,A ;briefly save
IN A,($FF) ;get the present video control port
; value
AND $80 ;save the EXROM select
OR B ;/OR in the requested mode
OUT ($FF),A ;\ and output to the port
LD A,B ;/save the requested mode to
LD (VIDMOD),A ;\VIDMOD
JR M0F3D ;we are outta here
;the present mode is not zero and the requested mode is zero, so
; prepare to move everything back around as needed
M0F01: CALL CLDFIL ;close the display file
LD BC,$97C0 ;/
LD HL,(ERRSP) ;|update ERRSP to new
AND A ;|stack location
SBC HL,BC ;|
LD (ERRSP),HL ;\
LD HL,(LISTSP) ;/
AND A ;|do the same for the
SBC HL,BC ;|LISTSP
LD (LISTSP),HL ;\
LD HL,(MSTBOT) ;/
AND A ;|yet again for MSTBOT
SBC HL,BC ;|
LD (MSTBOT),HL ;\
LD BC,$12C0 ;number of bytes to delete
LD HL,$6840 ;start address
LD DE,DELREC ;/delete the bytes
PUSH DE ;\
LD DE,$FF00 ;/HOME bank, all
PUSH DE ;\ chunks
LD DE,$0000 ;/
PUSH DE ;|no params in or out
PUSH DE ;\
CALL $5200+CALL_BANK ;
JR M0F3D ;we are done
M0F3A: SCF ;/set carry flag (indicates error)
JR M0F3E ;\and exit
M0F3D: AND A ;reset carry flag (all's OK)
M0F3E: POP AF ;/
POP HL ;|restore caller's registers
POP DE ;|
POP BC ;\
RET ;
;******************************************************************
; Module: PASSING
; Routine: PASSIN
;******************************************************************
PASSIN:
LD BC,(CHADD)
;I don't have a clue what this is trying to do. $255D in the home
; bank is the last byte of a CALL $65D0 ($65) and then presses on
; to call END? at $1B44 that lands us on a RST $38 that calls
; the RAM interrupt service
CALL M255D
LD HL,(CHADD)
AND A
SBC HL,BC
DEC HL
LD A,L
LD HL,(STKEND)
LD (HL),A
INC HL
POP BC
LD (HL),B
INC HL
LD (HL),C
INC HL
LD (STKEND),HL
LD HL,(CHADD)
DEC HL
BIT 0,A
JR Z,M0F73 ;
M0F67: DEC A
LD B,(HL)
DEC HL
DEC A
JP M ,M0F7D
LD C,(HL)
DEC HL
PUSH BC
JR M0F67 ;(0F67)
M0F73: LD B,$20
AND A
RET Z
LD C,(HL)
DEC HL
DEC A
PUSH BC
JR M0F67 ;(0F67)
M0F7D: LD HL,(STKEND)
DEC HL
LD A,(HL)
DEC HL
LD (STKEND),HL
LD H,(HL)
LD L,A
PUSH HL
RET
;******************************************************************
; Module: BS
; Routine: GOTO_B
;******************************************************************
GOTO_B:
M0F8A: PUSH AF ;/determine where the function
LD A,(VIDMOD) ;| dispatcher is located
AND A ;\
JR Z,M0F95 ;jump to normal fn dispatch
POP AF ;restore AF
JP MFD32 ;jump to high fn dispatch
M0F95: POP AF ;restore AF
JP $5200+GOTO_BANK ;
;******************************************************************
; Module: BS
; Routine: CALL_B
;******************************************************************
CALL_B:
M0F99: PUSH AF ;save AF
LD A,(VIDMOD) ;/check VIDMOD
AND A ;\
JR Z,M0FA4 ;jump if non-expanded video mode
POP AF ;restor AF
JP MFD90 ;jump to expanded video mode function dispatcher
M0FA4: POP AF ;restore AF
JP $5200+CALL_BANK ;jump to normal function dispatcher
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFC STKSZ = $200
DEFC SADDPT = $F5
DEFC SDATPT = $F6
DEFC HS = $40
DEFC HS_LSN = HS
DEFC BNA = $80
DEFC HS_MSN = BNA
DEFC ABN = $A0
DEFC HSP = ABN
DEFC STA_L = ABN
DEFC CMD = $C0
DEFC STA_O = CMD
DEFC LOWNYB = $C000
DEFC FREE_BYTES = 32
DEFC PRMOUT = 8
DEFC HOR_SEL = 10
DEFC BANK = 11
DEFC UPD_K = $02E1
DEFC DKHSPT = $F4
DEFC HREXPT = $FF
DEFC PRM_OUT = 8
; DISPATCH (SVC_CODE: PASSED ON STACK)
;
; SVC_CODE IS A 16 BIT QUANTITY. BIT 15 IS USED AS A JUMP FLAG: IF
; SET, THE DISPATCHER WILL TO A GOTO_BANK TO THE SPECIFIED ROUTINE,
; OTHERWISE IT WILL DO A CALL_BANK.
;
;
DEFC JMPTBL = $1FFF
DEFC LAST_EXT_SVC = 13
DEFC LAST_RAM_SVC = 24
;
;
; ORG $6200
ORG $1000
DEFC DISPATCH = $6200
LD IX,0 ;IX = SP
ADD IX,SP ;
PUSH BC ;RESERVE A WORD ON THE STACK
PUSH AF ;SAVE REGS
PUSH BC
PUSH DE
PUSH HL
LD E,(IX+2)
LD D,(IX+3) ;DE = SVC_CODE
XOR A
SLA E
RL D ;DE = 2*DE
RLA
LD HL,LAST_EXT_SVC
SLA L
RL H ;HL = 2*HL
AND A
SBC HL,DE ;COMPARE HL AND DE
JR NC,D_EXT ;IF DE <= HL
LD HL,LAST_RAM_SVC
SLA L
RL H
AND A
SBC HL,DE
JR C,D_HOME
LD B,255 ;HERE FOR RAM-BASED SERVICES
CALL $5200+GET_STATUS ;GET STATUS OF HOME BANK
LD B,255 ;BC=HOME BANK/HORIZ SELECT
JR D_SAVE
D_EXT: LD B,254 ;HER FOR EXT ROM BASE SERVICES
LD C,$FE
JR D_SAVE
D_HOME: LD B,255 ;SET BANK_ENABLE PARAMS FOR HOME
LD C,0
D_SAVE: PUSH AF
PUSH BC ;SAVE JUMP FLAG AND BANK_ENABLE PARAMS
LD HL,JMPTBL ;CALC ADR OF TABLE ENTRY
SCF
SBC HL,DE
LD B,254
CALL $5200+GET_WORD ;READ TABLE ENTRY
EX DE,HL
POP BC
POP AF ;RESTORE JUMP FLAG ETC
AND A
JR Z,D_CALL
LD (IX+(-2)),C ;PUT BANK AND HORZ SEL ON STACK
LD (IX+(-1)),B
LD L,(IX+0) ;SAVE RET ADDR
LD H,(IX+1)
LD (IX+3),H ;PUT RET ADDR BACK ON STACK
LD (IX+2),L
LD (IX+1),D ;SET UP STACK FOR GOTO_BANK
LD (IX+0),E ;PUT ADDR ON STACK
POP HL ;RESTORE REGS
POP DE
POP BC
POP AF
CALL $5200+GOTO_BANK ;HERE IF JUMP FLAG NOT SET
D_CALL: LD L,(IX+0) ;SET UP STACK FOR CALL_BANK
LD H,(IX+1) ;PUT RET ADDR IN PROPER LOC
PUSH HL
LD L,(IX+4)
LD H,(IX+5)
LD (IX+(-2)),L
LD (IX+(-1)),H
LD L,(IX+6) ;PUT PARM_OUT IN PROPER LOC
LD H,(IX+7)
LD (IX+0),L
LD (IX+1),H
LD (IX+2),C ;PUT BANK#, HS ON STACK
LD (IX+3),B
LD (IX+4),E ;PUT ADDR ON STACK
LD (IX+5),D
POP HL
LD (IX+6),L
LD (IX+7),H
POP HL ;RESTORE REGS
POP DE
POP BC
POP AF
CALL $5200+CALL_BANK ;HERE IF JUMP FLAG NOT SET
RET
;RST 56: HERE TO SERVICE INTERRUPT BY READING KEYBOARD
INT: PUSH AF
PUSH HL
PUSH IX
LD HL,0
ADD HL,SP
PUSH DE
LD A,(BS_MAX_BANK)
LD E,A
LD D,0
INC DE
INC DE
AND A
SBC HL,DE
EX DE,HL
LD IX,0
ADD IX,DE
POP DE
LD SP,IX
CALL $5200+SAVE_STATUS
PUSH BC
LD B,$FF
CALL $5200+GET_STATUS
LD B,$FF
LD A,C
AND $F8
LD C,A
CALL BANK_ENABLE ;AAA
POP BC
LD HL,(FRAMES) ;INCREMENT FRAMES COUNTER
INC HL
LD (FRAMES),HL
LD A,H
OR L
JR NZ,LIT3
INC (IY+(FRAMES2-Y)) ;
LIT3: PUSH BC
PUSH DE
CALL UPD_K
POP DE
POP BC
PHLAF: ;JUMP HERE TO POP HL, POP AF, ENABLE INTERRUPTS AND RETURN
LD IX,0
ADD IX,SP
CALL $5200+RESTORE_STATUS
INC IX
LD SP,IX
POP IX
POP HL
POP AF
EI
RET
;HERE TO SERVICE THE NON-MASKABLE INTERRUPT
;IF (NMIADD)=0 THEN RETURNS STRAIGHT AWAY;
;ELSE, JUMPS TO (NMIADD) WHIT HL (ON TOP) , AF & RETN ADDR ON
;THE STACK
NMI: PUSH AF
PUSH HL
LD HL,(USRNMI)
LD A,H
OR L
JR NZ,LNI3
JP (HL)
LNI3: POP HL
POP AF
RETN
;
;
DEFC BS_MAX = $5200+ASMPC
DEFC BS_MAX_BANK = BS_MAX
DEFB $FF ;LOCAL COPY OF MAX_BANK
;
; GET_WORD (ADDR: HL, BANK: B, WORD: HL)
;
GET_WORD: PUSH AF ;SAVE REGS
PUSH BC
PUSH DE
CALL $5200+GET_NUMBER ;GET BANK# OF OWNER OF ADDR
PUSH AF
LD D,B
LD B,A
CALL $5200+GET_STATUS ;GET STATUS OF OWNER
PUSH BC
CALL $5200+GET_CHUNK ;SET HS FOR GETTING AT ADDR
CPL ;PUT IN ACTIVE LOW FORMAT
LD B,D
LD C,A
CALL BANK_ENABLE ;ENABLE ADDR
LD E,(HL) ;WRITE THE WORD
INC HL
LD D,(HL)
DEC HL
EX DE,HL
POP BC
POP AF
LD B,A
CALL BANK_ENABLE ;REENABLE OWNER OF ADDR
POP DE
POP BC
POP AF
RET
;
; PUT_WORD (WORD: DE, ADDR: HL, BANK: B)
;
PUT_WORD: PUSH AF
PUSH BC
CALL $5200+GET_NUMBER
PUSH AF
LD D,B
LD B,A
CALL $5200+GET_STATUS
PUSH BC
CALL $5200+GET_CHUNK
CPL
LD B,D
LD C,A
CALL BANK_ENABLE ;BBB
LD (HL),E
INC HL
LD (HL),D
DEC HL
POP BC
POP AF
CALL BANK_ENABLE ;CCC
POP BC
POP AF
RET
;
; WRITE_BS_REG (REG_ADDR: D, REG_DATA: E)
;
WRITE_BS_REG: PUSH AF ;SAVE REGS
PUSH BC
PUSH HL
LD H,D
LD L,0 ;HL = MEMORY MAPPED ADR
LD A,(LOWNYB) ;SAVE ($E000)
PUSH AF
LD A,(HL) ;SAVE (HL)
PUSH AF
LD A,7
OUT (SADDPT),A ;SAVE VALUES OF SOUND REGS $07 AND $0E
IN A,(SDATPT)
LD B,A
LD A,$0E
OUT (SADDPT),A
IN A,(SDATPT)
LD C,A
LD A,7 ;SET IOA CHANNEL TO OUTPUT
OUT (SADDPT),A
LD A,$40
OUT (SDATPT),A
LD A,$0E
OUT (SADDPT),A
XOR A
OUT (SDATPT),A
LD A,2
LD (LOWNYB),A ;RESET NYBBLE STEERING LOGIC
LD A,E
LD (HL),A ;WRITE LSN OF DATA
SRA A
SRA A
SRA A
SRA A
LD (HL),A ;WRITE MSN OF DATA
LD A,7 ;RESTORE SOUND REGS
OUT (SADDPT),A
LD A,B
OUT (SDATPT),A
LD A,$0E
OUT (SADDPT),A
LD A,C
OUT (SDATPT),A
POP AF
LD (HL),A ;RESTORE (HL)
POP AF
LD (LOWNYB),A ;RESTORE ($E000)
POP HL ;RESTORE REGS
POP BC
POP AF
RET
;
; READ_BS_REG (LSN_ADDR: D, MSN_ADDR: E, BYTE_DATA: C)
;
READ_BS_REG: PUSH AF ;SAVE REGS
PUSH BC
PUSH HL
LD H,D
LD L,0 ;HL=MEMORY MAPPED ADDR
LD A,(LOWNYB) ;SAVE ($E000)
PUSH AF
LD A,(HL) ;SAVE (HL)
PUSH AF
LD A,7
OUT (SADDPT),A ;SAVE VALUES OF SOUND REGS $07 AND $0E
IN A,(SDATPT)
LD B,A
LD A,$0E
OUT (SADDPT),A
IN A,(SDATPT)
LD C,A
PUSH BC
LD A,7 ;SET IOA CHANNEL TO OUTPUT
OUT (SADDPT),A
LD A,$40
OUT (SDATPT),A
LD A,$0E
OUT (SADDPT),A
XOR A
OUT (SDATPT),A
LD A,2
LD (LOWNYB),A ;RESET NYBBLE STEERING LOGIC
LD A,(HL) ;READ LSN OF DATA
AND $0F
LD C,A
LD H,E
LD A,(HL) ;READ MSN OF DATA
SLA A
SLA A
SLA A
SLA A
OR C
LD E,A ;RETURN BYTE DATA IN E
POP BC ;POP SAVED SOUND REG DATA
LD A,7 ;RESTORE SOUND REGS
OUT (SADDPT),A
LD A,B
OUT (SDATPT),A
LD A,$0E
OUT (SADDPT),A
LD A,C
OUT (SDATPT),A
POP AF
LD (HL),A ;RESTORE (HL)
POP AF
LD (LOWNYB),A ;RESTORE ($E000)
POP HL ;RESTORE REGS
POP BC
POP AF
RET
;
; GET_BANK_STATUS (BANK: B, STATUS: B, HORIZONTAL_SELECT: C)
;
GET_STATUS: PUSH AF ;SAVE REGS
PUSH DE
LD A,B
CP $FE
JR Z,GS_EXT ;IF BANK=254
CP $FF
JR Z,GS_HOME ;IF BANK=255
AND A
JR Z,GS_DOCK ;IF BANK=0
LD D,BNA ;HERE IF EXP BANK
LD E,B
CALL $5200+WRITE_BS_REG
LD D,HS_LSN
LD E,HS_MSN
CALL $5200+READ_BS_REG ;READ HS
LD A,E
CPL
LD C,A
LD D,STA_L
LD E,STA_O
CALL $5200+READ_BS_REG ;READ STATUS NYBBLES
LD B,E
JR GS_EXIT
GS_HOME: LD BC,0 ;RETURN 0 FOR HOME BANK STATUS
JR GS_EXIT
GS_DOCK: IN A,(DKHSPT) ;RETURN DOCK BANK STATUS)
CPL
LD B,A
LD C,0
JR GS_EXIT
GS_EXT: IN A,(HREXPT)
AND $80 ;CLEAR ALL BITS BUT BIT 7
CPL
RLCA ;PUT ACTIVE BIT IN BIT ZERO
LD B,A
IN A,(DKHSPT)
CPL
AND 1
OR B
LD B,A
LD C,0
GS_EXIT: POP DE ;RESTORE REGISTERS
POP AF
RET
;
; GET_CHUNK (ADDR: HL, MASK: A)
;
GET_CHUNK: PUSH BC ;SAVE B
LD A,H ;CHUNK NUMBER=HIGH 3 BITS OF
LD B,5 ; H SO SHIFT RIGHT 3 BITS
GC_SHIFT: SRL A
DJNZ GC_SHIFT
INC A ;CREATE MASK BY ROLLING A 1
LD B,A ; LEFT CHUNK NUMBER+1 TIMES
XOR A ; THE FLAG COMES FROM THE CARRY
SCF
GC_ROLL: RLA
DJNZ GC_ROLL
POP BC ;RESTORE B
RET
;
;GET_BANK_NUMBER (ADDR: HL, BANK_NUMBER: A)
;
GET_NUMBER: PUSH BC ;SAVE REGS
PUSH DE
CALL $5200+GET_CHUNK
LD C,A
LD A,(BS_MAX_BANK) ;GET LARGEST BANK NUMBER
AND A
JR Z,GN_RD_DOCK ;IF NO EXP BANKS
LD B,A
GN_CHECK: LD E,B ;SEARCH ALL EXP BANKS
CALL $5200+GET_STATUS
AND C
JR Z,GN_EXP ;FOUND THE CHUNK, SO EXIT THE LOOP
DJNZ GN_CHECK
GN_RD_DOCK: IN A,(DKHSPT) ;NOT IN EXP BANKS SO CHECK DOCK
CPL
AND C
JR Z,GN_DOCK
DEC C ;IF CHUNK>1, THEN CAN'T BE IN EXT
JR NZ,GN_HOME
IN A,(HREXPT) ;CHECK IF IN EXT BANK
AND $80
LD D,A
IN A,(DKHSPT)
AND 1
RRCA
AND D
JR Z,GN_HOME ;NOT IN EXT BANK
LD A,$FE ;IN EXT BANK SO RETURN 254
JR GN_EXIT
GN_HOME: LD A,$FF ;IN HOME BANK, SO RETURN 255
JR GN_EXIT
GN_DOCK: XOR A ;FOUND IN DOCK SO RETURN 0
JR GN_EXIT
GN_EXP: LD A,B ;RETURN EXP BANK NUMBER
GN_EXIT: POP DE ;RESTORE REGS
POP BC
RET
;
;BANK_ENBALE (BANK: B, HORIZONTAL_SELECT: C)
;
X_BANK_ENABLE: PUSH AF ;/SAVE REGS
PUSH BC ;|
PUSH DE ;|
PUSH HL ;\
LD H,B ;bank to H
LD A,(BS_MAX_BANK) ;GET LARGEST BANK NUMBER
AND A ;
JR Z,BE_SKIP ;IF NO EXP BANKS
LD D,BNA ;
LD E,0 ;
CALL $5200+WRITE_BS_REG ;
LD D,HSP ;
PUSH AF ;
LD A,C ;
CPL ;
LD E,A ;
POP AF ;
CALL $5200+WRITE_BS_REG ;TURN OFF APPROPRIATE BITS OF
; ALL EXP BANKS
BE_SKIP: LD A,B
AND A
JR NZ,BE_NTDOCK
LD A,C
CP $FF
JR Z,BE_EXT_OK
IN A,(HREXPT) ;HERE FOR DOCK
RES 7,A
OUT (HREXPT),A
BE_EXT_OK: LD A,C
CPL
OUT (DKHSPT),A ;ENABLE DOCK
JR BE_EXIT
BE_NTDOCK: LD A,B ;CHECK IF EXT
CP $FE
JR NZ,BE_NTEXT
IN A,(HREXPT) ;HERE FOR EXT
RLA
RR C
CCF
RRA
OUT (HREXPT),A
BIT 7,A
JR NZ,BE_SET
IN A,(DKHSPT)
RES 0,A
OUT (DKHSPT),A
JR BE_EXIT
BE_SET: IN A,(DKHSPT)
SET 0,A
OUT (DKHSPT),A
JR BE_EXIT
BE_NTEXT: IN A,(DKHSPT) ;DISABLE DOCK
CPL
LD E,A
LD A,C
CPL
OR E
CPL
OUT (DKHSPT),A
BIT 0,C
JR NZ,BE_CHK_HOME
IN A,(HREXPT) ;DISABLE EXT
RES 7,A
OUT (HREXPT),A
IN A,(DKHSPT)
RES 0,A
OUT (DKHSPT),A
BE_CHK_HOME: LD A,B ;CHECK IF HOME
CP $FF
JR Z,BE_EXIT ;IS HOME, SO DONE
LD D,BNA ;WRITE NEW EXP BANK STATUS
LD E,B
CALL $5200+WRITE_BS_REG
LD D,HS
LD A,C
CPL
LD E,A
CALL $5200+WRITE_BS_REG
BE_EXIT: POP HL ;RESTORE REGS
POP DE
POP BC
POP AF
RET
;
; SAVE_BANK_STATUSES (STATUS_ADR: IX)
; PUSHES THE STATUS OF ALL BANKS ONTO THE STACK (IX)
;
SAVE_STATUS: PUSH AF ;SAVE REGS
PUSH BC
PUSH DE
IN A,(HREXPT) ;SAVE EXT BANK STATUS
NOP ; LEAVE BITS 0-6 ALONE. NOPS PUT IN
NOP ; TO KEEP ADDRS THE SAME
LD (IX+0),A
INC IX
IN A,(DKHSPT) ;GET DOCK BANK STATUS
LD (IX+0),A
INC IX
LD A,(BS_MAX_BANK) ;GET NUMBER OF BANKS
AND A
JR Z,SS_EXIT
LD B,A ;SET UP BANK COUNTER
SS_LOOP: LD E,B ;BANK NUMBER INTO E
CALL $5200+GET_STATUS ;GET STATUS OF BANK IN b
LD (IX+0),C
INC IX
LD B,E
DJNZ SS_LOOP ;AROUND FOR ALL
SS_EXIT: DEC IX
POP DE ;RESTORE REGS
POP BC
POP AF
RET
;
; RESTORE_BANK_STATUSES (STATUS_ADR: IX)
; RESTORES THE STATUS OF ALL BANKS FROM THE STACK (IX)
;
RESTORE_STATUS: PUSH AF ;SAVE REGS
PUSH BC
PUSH DE
LD A,(IX+0) ;GET EXT ROM STATUS
OUT (HREXPT),A
INC IX
LD A,(IX+0) ;GET DOCK BANK STATUS
OUT (DKHSPT),A
INC IX
LD A,(BS_MAX_BANK) ;GET NUMBER OF BANKS
AND A
JR Z,RS_EXIT
LD B,A ;SET UP BANK COUNTER
RS_LOOP: LD C,(IX+0)
CALL BANK_ENABLE ;WRITE BANK STATUS OF BANK IN B
INC IX
DJNZ RS_LOOP
RS_EXIT: DEC IX
POP DE
POP BC
POP AF
RET
;
; GOTO_BANK (BANK, HORIZONTAL_SELECT, ADDR: PASSED ON STACK)
; SETS UP THE DESTINATION BANK AND JUMPS WITHOUT RETURN ADDRESS
; IN BANK
;
GOTO_BANK: LD IX,0 ;SET IX TO SP
ADD IX,SP
LD (IX+0),C ;SAVE BC AND TRASH CALLER'S RETURN ADDRESS
LD (IX+1),B
LD C,(IX+2) ;SET PARAMS FOR BANK_ENABLE
LD B,(IX+3)
CALL BANK_ENABLE ;DDD
POP BC ;RESTORE BC
POP IX ;TRASH PARAMS TO GOTO_BANK
POP IX ;GET ADDR
JPIX: JP (IX)
;
; CALL_BANK (ADDR, BANK, HORIZONTAL_SELECT, PRM_OUT, PRM_IN)
; ALL INPUT PARAMETERS ARE PUSHED ON THE STACK
;
; CLOBBERS IX
;
; SETS UP THE BANK AND MAKES A JUMP WITH RETURN ADDRESS TO
; ADDRESS IN BANK
DEFC BS_STACK = $6200+ASMPC-$1000
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFC BS_SP = $5200+ASMPC
DEFW $FFFF
CALL_BANK: EX (SP),HL ;GET RET ADDR
LD IX,(BS_SP)
DEC IX
LD (IX+0),H
DEC IX
LD (IX+0),L ;PUSH HL ON BS_STACK
POP HL
EX (SP),HL ;GET PARAM_IN
DEC IX
LD (IX+0),H
DEC IX
LD (IX+0),L
LD (BS_SP),IX
PUSH DE
PUSH BC
PUSH AF
LD HL,0
ADD HL,SP ;HL = SP
LD D,H
LD E,L
LD A,(BS_MAX_BANK)
LD C,A
LD B,0
INC BC
INC BC ;BC = MAX_BANK+2
AND A
SBC HL,BC
LD SP,HL
LD IX,0
ADD IX,DE
EX DE,HL ;DE, HL NOW CONTAIN DEST, SRC
; POINTERS FOR A BLOCK MOVE
LD C,(IX+PRM_OUT)
LD B,(IX+PRM_OUT)
LD A,14
ADD A,C
LD C,A
JR NC,CB_NC1 ;BC = PRM_OUT + 14
INC B
CB_NC1: LDIR ;MAKE ROOM FOR BANK STATUS
PUSH DE
POP IX ;IX = DE
CALL $5200+SAVE_STATUS
LD IX,0
ADD IX,SP
LD C,(IX+HOR_SEL) ;GET PARAMS FOR BANK_ENABLE
LD B,(IX+BANK)
CALL BANK_ENABLE ;ENABLE DESTINATION BANK
POP AF ;RESTORE REGS
POP BC
POP DE
POP HL
POP IX ;TRASH PARAMS TO CALL_BANK AND GET ADDR
POP IX
POP IX
CALL $5200+JPIX
PUSH AF
PUSH BC
PUSH DE
PUSH HL
LD IX,(BS_SP)
LD C,(IX+0)
INC IX
LD B,(IX+0)
INC IX ;POP PRM_IN OFF BS_STACK
LD (BS_SP),IX ;UPDATE BS_SP
LD IX,0
ADD IX,SP
LD A,8
ADD A,C
LD C,A
JR NC,CB_NC2 ;BC = PRM_IN + 8
INC B
CB_NC2: ADD IX,BC ;IX = SP + PRM_IN +9
PUSH IX
POP HL ;HL=IX
DEC HL ;HL = SRC POINTER FOR BLOCK MOVE
CALL $5200+RESTORE_STATUS
PUSH IX
POP DE ;DE= DEST POINTER FOR BLOCK MOVE
LDDR ;DEALLOCATE SPACE FOR BANK STATUS
EX DE,HL
INC HL
LD SP,HL ;RESTORE SP
LD IX,(BS_SP)
LD C,(IX+0)
INC IX
LD B,(IX+0)
INC IX ;POP RET ADDR OF BS_STACK
LD (BS_SP),IX ;UPDATE BS_SP
PUSH BC
POP IX
POP HL
POP DE ;RESTORE REGISTERS
POP BC
POP AF
PUSH IX
RET
;
; HERE ARE SOME EQUATES WHICH ARE USED BY XFER_BYTES AND THE ROUTINES IT
; CALLS
;
DEFC DIRECTION = 0
DEFC BUF_PTR = 0
DEFC LENGTH = 2
DEFC DEST_ADDR = 4
DEFC SRC_ADDR = 6
DEFC DEST_BANK = 8
DEFC SRC_BANK = 9
;
; MOVE_BYTES (BYTES_TO MOVE: DE, DIRECTION: A)
;
MOVE_BYTES: PUSH HL ;SAVE REGISTERS
PUSH DE
PUSH BC
LD C,B
LD B,(IX+SRC_BANK)
CALL BANK_ENABLE ;FFF
LD B,D
LD C,E
LD E,(IX+BUF_PTR)
LD D,(IX+BUF_PTR+1)
LD L,(IX+SRC_ADDR)
LD H,(IX+SRC_ADDR+1)
RLCA
RRCA
JR C,MB_RV1 ;IF A<0
LDIR
ADD HL,BC
JR MB_UP1
MB_RV1: LDDR
AND A
SBC HL,BC ;DECREMENT POINTER
MB_UP1: LD (IX+SRC_ADDR),L ;STORE NEW POINTER VALUE
LD (IX+SRC_ADDR+1),H
POP BC
POP HL
PUSH HL
PUSH BC
LD B,(IX+DEST_BANK)
CALL BANK_ENABLE ;SELECT DEST BANK
LD B,H ;MOVE FROM STACK TO DEST
LD C,L
LD E,(IX+DEST_ADDR)
LD D,(IX+DEST_ADDR+1)
LD L,(IX+BUF_PTR)
LD H,(IX+BUF_PTR+1)
RLCA
RRCA
JR C,MB_RV2 ;IF A<0
LDIR
ADD HL,BC ;INCREMENT POINTER
JR MB_UP2
MB_RV2: LDDR
AND A
SBC HL,BC ;DECREMENT POINTER
MB_UP2: LD (IX+DEST_ADDR),L ;STORE NEW POINTER VALUE
LD (IX+DEST_ADDR+1),H
POP BC
POP DE
POP HL
RET
;
; CREATE_BITMAP (ADDR: HL, BITMAP: A)
;
CREATE_BITMAP: LD D,H ;SAVE START ADR
LD E,L
LD C,(IX+LENGTH)
LD B,(IX+LENGTH+1)
LD A,(IX+DIRECTION)
RLCA ;CALCULATE END ADDR
RRCA
JR C,CB_SUB ;IF A<0
ADD HL,BC
JR CB_CONT
CB_SUB: SBC HL,BC
CB_CONT: CALL $5200+GET_CHUNK ;GET END CHUNK BIT
CPL
LD B,A
EX DE,HL
CALL $5200+GET_CHUNK ;GET START CHUNK BIT
CPL
LD C,A
XOR B
JR Z,CB_EXIT
LD A,C ;HERE IF START AND END CHUNKS
AND B ; ARE NOT THE SAME
LD B,A ;PUT START AND END BITS TOGETHER AND
LD C,0 ; FILL BETWEEN THEM WITH ZEROES
SCF
CB_NB1: LD A,B ;TEST NEXT BIT
RL C
AND C
JR NZ,CB_NB1 ;OTHERWISE, FOUND FIRST ZERO
CB_NB2: LD A,B ;TEST NEXT BIT
RL C
AND C
JR Z,CB_EXIT ;FOUND LAST ZERO
XOR B ;OTHERWISE, UPDATE BITMAP
LD B,A
JR CB_NB2
CB_EXIT: LD A,B
RET ;RETURN BITMAP
;
; XFER_BYTES (DIRECTION, LENGTH, DEST_ADDR, SRC_ADDR, DEST_BANK,
; SRC_BANK,: PASSED ON STACK IN ORDER SHOWN: STATUS_CODE: A)
;
; ALL PARAMETERS ON STACK HAVE OFFSETS DEFINED ABOVE
XFER_BYTES: PUSH AF ;SAVE REGS
PUSH BC
PUSH DE
PUSH HL
LD HL,0
ADD HL,SP
LD DE,10
ADD HL,DE
EX DE,HL ;DE POINTS TO START OF PARAMS
LD A,(BS_MAX_BANK)
LD C,A
LD B,0
LD HL,0
ADD HL,SP
AND A
SBC HL,BC
DEC HL
DEC HL ;HL=SP-MAX_BANK-2
PUSH HL
POP IX ;IX POINTS TO LOCATION TO SAVE STATUS
LD SP,IX
CALL $5200+SAVE_STATUS ;SAVE BANKS' STATUS
PUSH DE
POP IX ;IX POINTS TO PARAMS
LD L,(IX+SRC_ADDR)
LD H,(IX+SRC_ADDR+1)
CALL $5200+CREATE_BITMAP ;GET SRC BITMAP
PUSH AF ;SAVE ON STACK TEMPORARILY
LD L,(IX+DEST_ADDR)
LD H,(IX+DEST_ADDR+1)
CALL $5200+CREATE_BITMAP ;GET DESTINATION BIT MAP
LD C,A ;C=DEST BITMAP
POP AF
LD B,A ;B=SRC BITMAP
LD A,(IX+SRC_BANK)
LD D,(IX+DEST_BANK)
CP D ;COMPARE SRC AND DEST BANK NUMBERS
JR NZ,XB_DIFF_BANKS
LD A,B ;HERE IF BANK NUMBERS ARE DIFFERENT
AND C
LD B,A ;B=UNION OR SRC AND DEST BITMAPS
JR XB_DO_MOVE
XB_DIFF_BANKS: LD A,B ;CHECK FOR OVERLAP BETWEEN SRC AND
OR C ; DEST CHUNKS
CP $FF
JR NZ,XB_OVERLAP
LD E,B ;HERE IF NO OVERLAP
LD B,D
CALL BANK_ENABLE ;SELECT DEST BANK
XB_DO_MOVE: LD B,(IX+SRC_BANK)
LD C,E
CALL BANK_ENABLE ;SELECT DEST BANK
LD L,(IX+SRC_ADDR)
LD H,(IX+SRC_ADDR+1)
LD E,(IX+DEST_ADDR)
LD D,(IX+DEST_ADDR+1)
LD C,(IX+LENGTH)
LD B,(IX+LENGTH+1)
LD A,(IX+DIRECTION)
RLCA
RRCA
JR C,XB_REVERSE ;IF A<0
LDIR
JR XB_EXIT
XB_REVERSE: LDDR
JR XB_EXIT
XB_OVERLAP: LD HL,MSTBOT
PUSH BC
LD B,255
CALL $5200+GET_WORD
POP BC
LD DE,STKSZ
AND A
SBC HL,DE ;HL=ADDRESS OF STACK LIMIT
LD DE,FREE_BYTES
ADD HL,DE
EX DE,HL ;DE=SP_NEW
LD HL,0
ADD HL,SP ;HL=SP_OLD
INC DE ;COMPARE SP_OLD AND SP_NEW
AND A
SBC HL,DE
JR NC,XB_SPACE ;IF SP_OLD-SP_NEW > 0
LD A,1 ;RETURN ERROR CODE
JR XB_EXIT
XB_SPACE: DEC DE
EX DE,HL
LD SP,HL ;SET SP TO SP_NEW
INC DE ;DE=BUF_SZ
LD A,(IX+DIRECTION)
LD (IX+BUF_PTR),L
LD (IX+BUF_PTR+1),H
LD L,(IX+LENGTH)
LD H,(IX+LENGTH+1)
XB_MOVE_LOOP: AND A ;HL = BYTES LEFT TO MOVE
SBC HL,DE ;DE = BYTES TO MOVE THIS TIME
JR C,XB_LAST_MOVE ;IF LESS THAN BUF_SZ BYTES LEFT
CALL $5200+MOVE_BYTES
JR XB_MOVE_LOOP
XB_LAST_MOVE: ADD HL,DE
EX DE,HL
CALL $5200+MOVE_BYTES
EX DE,HL
LD L,(IX+BUF_PTR)
LD H,(IX+BUF_PTR+1)
ADD HL,DE ;HL = BUF_PTR+BUF_SZ
LD SP,HL ;RESTORE SP
XB_EXIT: XOR A ;RETURN CODE FOR SUCCESSFUL COMPLETION
LD IX,0
ADD IX,SP
CALL $5200+RESTORE_STATUS ;RESTORE STATE AND RETURN ZERO CODE
INC IX
LD SP,IX
POP HL ;RESTORE REGS
POP DE
POP BC
POP AF
POP IX ;CLEAN UP PARAMS
EX (SP),IX
POP IX
EX (SP),IX
POP IX
EX (SP),IX
POP IX
EX (SP),IX
POP IX
EX (SP),IX
RET
;
; GOTO_EXT_INIT (ADDR: HL)
;
GOTO_EXT: POP IX ;TRASH RET ADDR
PUSH AF
IN A,(HREXPT)
SET 7,A
OUT (HREXPT),A
LD A,1
OUT (DKHSPT),A
POP AF
JP (HL)
; ORG $1624
;$1624 to $17FF
BLK1: DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00
;$1700
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$80
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
;$1800 to $1BFF
;$1800
BLK2: DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
;$1900
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
;$1C00 to $1CFF
BLK3: DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
ORG $1D00
FIXTBL: DEFW DISPATCH+$32
DEFW DISPATCH+$4D
DEFW DISPATCH+$72
DEFW DISPATCH+$AB
DEFW $5200+INT+$0A
DEFW $5200+INT+$1F
DEFW $5200+INT+$25
DEFW $5200+INT+$2E
DEFW $5200+INT+$4D
DEFW $5200+GET_WORD+$04
DEFW $5200+GET_WORD+$0A
DEFW $5200+GET_WORD+$0E
DEFW $5200+GET_WORD+$14
DEFW $5200+GET_WORD+$1F
DEFW $5200+PUT_WORD+$03
DEFW $5200+PUT_WORD+$09
DEFW $5200+PUT_WORD+$0D
DEFW $5200+PUT_WORD+$13
DEFW $5200+PUT_WORD+$1C
DEFW $5200+GET_STATUS+$12
DEFW $5200+GET_STATUS+$19
DEFW $5200+GET_STATUS+$23
DEFW $5200+GET_NUMBER+$03
DEFW $5200+GET_NUMBER+$07
DEFW $5200+GET_NUMBER+$0F
DEFW BANK_ENABLE+$06
DEFW BANK_ENABLE+$13
DEFW BANK_ENABLE+$1A
DEFW BANK_ENABLE+$75
DEFW BANK_ENABLE+$7D
DEFW $5200+SAVE_STATUS+$14
DEFW $5200+SAVE_STATUS+$1C
DEFW $5200+RESTORE_STATUS+$12
DEFW $5200+RESTORE_STATUS+$1C
DEFW BS_SP
DEFW $5200+GOTO_BANK+$13
DEFW $5200+CALL_BANK+$03
DEFW $5200+CALL_BANK+$1D
DEFW $5200+CALL_BANK+$29
DEFW $5200+CALL_BANK+$4E
DEFW $5200+CALL_BANK+$5D
DEFW $5200+CALL_BANK+$6A
DEFW $5200+CALL_BANK+$72
DEFW $5200+CALL_BANK+$80
DEFW $5200+CALL_BANK+$96
DEFW $5200+CALL_BANK+$A2
DEFW $5200+CALL_BANK+$B0
DEFW $5200+MOVE_BYTES+$08
DEFW $5200+MOVE_BYTES+$34
DEFW $5200+CREATE_BITMAP+$15
DEFW $5200+CREATE_BITMAP+$1B
DEFW $5200+XFER_BYTES+$0E
DEFW $5200+XFER_BYTES+$2D
DEFW $5200+XFER_BYTES+$2E
DEFW $5200+XFER_BYTES+$38
DEFW $5200+XFER_BYTES+$54
DEFW $5200+XFER_BYTES+$5B
DEFW $5200+XFER_BYTES+$85
DEFW $5200+XFER_BYTES+$BA
DEFW $5200+XFER_BYTES+$C1
DEFW $5200+XFER_BYTES+$D4
DEFW 0 ;TABLE TERMINATOR
;******************************************************************
; Module: DISPATCH
; Routine: UNUSED1
;******************************************************************
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
;******************************************************************
; Module: DISPATCH
; Routine: JMPTBL
;******************************************************************
DEFW $1795 ;PUT_LN:
DEFW $2813 ;DRAWLN:
DEFW $2624 ;F_PNT:
DEFW $0939 ;SCRL:
DEFW $08A6 ;K_CLS:
DEFW $073F ;PUTMES:
DEFW $0566 ;P_NL:
DEFW $0554 ;P_RT:
DEFW $053A ;P_LFT:
DEFW $02B0 ;K_SCAN:
DEFW $0010 ;WRCH:
DEFW $11ED ;SENDCH:
DEFW $11CF ;RDCH:
DEFW $3C6C ;TO_THE:
DEFW $3C65 ;ROOT:
DEFW $3C5E ;ACS:
DEFW $3C4E ;ASN:
DEFW $3BFD ;ATN:
DEFW $3BF5 ;TAN:
DEFW $3BD0 ;SIN:
DEFW $3BC5 ;COS:
DEFW $3B9E ;ANGLE:
DEFW $3B2E ;LN:
DEFW $3ADF ;EXP:
DEFW $3ACA ;INT:
DEFW $3ABB ;INTDIV:
DEFW $3656 ;FLOAT:
DEFW $35D3 ;TRUNC:
DEFW $356E ;DIVIDE:
DEFW $3489 ;TIMES:
DEFW $3468 ;MULT:
DEFW $33D3 ;ADD:
DEFW $33CE ;TSSUB:
DEFW $31A1 ;OUTPUT:
DEFW $3193 ;FP2A:
DEFW $3160 ;FP2BC:
DEFW $30F9 ;ININT:
DEFW $30E9 ;STK_EC:
DEFW $30E6 ;STK_A:
DEFW $3059 ;STKUSN:
DEFW $2FC0 ;DIM:
DEFW $2FAF ;POPSTR:
DEFW $2EBD ;LET:
DEFW $2E74 ;PAEDCB:
DEFW $2E70 ;PSHSTR:
DEFW $2C70 ;FIND_N:
DEFW $29F2 ;F_INKY:
DEFW $29E5 ;F_PI:
DEFW $29B6 ;RND:
DEFW $28D7 ;F_ATTR:
DEFW $288E ;F_SCRN:
DEFW $2854 ;EXPRN:
DEFW $2810 ;DRAW_L:
DEFW $26DB ;DRAW:
DEFW $2679 ;CIRCLE:
DEFW $2660 ;GET_XY:
DEFW $263E ;PLOTBC:
DEFW $2635 ;PLOT:
DEFW $2603 ;SCRMBL:
DEFW $241D ;HIFLSH:
DEFW $23DE ;COLOR:
DEFW $2380 ;NOTKBQ:
DEFW $226B ;ISEQ:
DEFW $222B ;INPUT:
DEFW $217E ;P_SEQ:
DEFW $2159 ;K_PRIN:
DEFW $2155 ;K_LPR:
DEFW $201D ;DEF:
DEFW $2009 ;BREAKQ:
DEFW $1FEB ;PAUSE:
DEFW $1FD4 ;RETURN:
DEFW $1FBB ;CHK_SZ:
DEFW $1F99 ;GO_SUB:
DEFW $1F39 ;CLR_BC:
DEFW $1F36 ;CLEAR:
DEFW $1F23 ;FIX_U:
DEFW $1F1E ;FIX_Ul:
DEFW $1EF1 ;JUMP:
DEFW $1EE4 ;CONT:
DEFW $1ED4 ;RAND:
DEFW $1ECA ;RESTBC:
DEFW $1E82 ;DATA:
DEFW $1D97 ;READ:
DEFW $1D55 ;NEXT:
DEFW $1C59 ;STOP:
DEFW $1C78 ;FOR:
DEFW $1AD8 ;EXCUTE:
DEFW $1A27 ;SYNTAX:
DEFW $1788 ;PUT_BC:
DEFW $1750 ;DELREC:
DEFW $1720 ;RECLEN:
DEFW $16F0 ;SUBLIN:
DEFW $16D6 ;FIND_L:
DEFW $160D ;FLASHA:
DEFW $25D0 ;MOVE:
DEFW $25CC ;FORMAT:
DEFW $25D4 ;ERASE:
DEFW $25C8 ;CAT:
DEFW $1465 ;OPCHAN:
DEFW $142A ;OPEN:
DEFW $13BE ;CLCHAN:
DEFW $139F ;CLOSE:
DEFW $1354 ;RESET:
DEFW $12BB ;INSERT:
DEFW $1230 ;SELECT:
DEFW $11E1 ;INCH:
DEFW $0D31 ;INIT:
DEFW $0D1D ;K_NEW:
DEFW $0D0D ;DESLUG:
DEFW $0A4A ;PRSCAN:
DEFW $0A23 ;DUMPPR:
DEFW $08EA ;CLS:
DEFW $08A9 ;CLLHS:
DEFW $0888 ;R_ATTS:
DEFW $0710 ;ATTBYT
DEFW $05B2 ;SET_AT
DEFW $0500 ;SEND_TV
DEFW $0A02 ;K_DUMP
DEFW $0436 ;BEEP
DEFW $03F3 ;PARP
DEFW $02E1 ;UD_K start of home rom services
DEFW $FFFF ; RESERVED24:
DEFW $FFFF ; RESERVED23:
DEFW $FFFF ; RESERVED22:
DEFW $FFFF ; RESERVED21:
DEFW $FFFF ; RESERVED20:
DEFW $6721 ;XFER_BYTES?($6722) RESERVED19:
DEFW $65CF ;CALL_BANK? ($65CF) RESERVED18:
DEFW $6571 ;GOTO_BANK? ($6571) RESERVED17:
DEFW $6499 ;BANK_ENABLE RESERVED16:
DEFW $645E ;GET_NUMBER GET_NUMBER:
DEFW $6405 ;GET_STATUS GET_STATUS:
DEFW $FFFF ; RESERVED13:
DEFW $FFFF ; RESERVED12:
DEFW $FFFF ; RESERVED11:
DEFW $FFFF ; RESERVED10:
DEFW $00E5 ;W_BORD RESERVED9:
DEFW $0EA3 ; RESERVED8:
DEFW $0851 ;SAVE RESERVED7:
DEFW $06E5 ; RESERVED6:
DEFW $05CC ;LOAD RESERVED5:
DEFW $01AB ;SLVM RESERVED4:
DEFW $018D ;R_EDGE RESERVED3:
DEFW $0189 ;RD_BIT RESERVED2:
DEFW $00FC ;RD_TAPE RESERVED1: EXROM services
DEFW $0068 ;
; Apparently the linker needs this to generate the correct addresses
; Why? Who knows?
ORG 0
; END
[/sourcecode]