1244 lines
97 KiB
Plaintext
1244 lines
97 KiB
Plaintext
******************************************************************
|
|
* *
|
|
* DOS's warmstart routine *
|
|
* *
|
|
*----------------------------------------------------------------*
|
|
* *
|
|
* The DOS cold- and warmstart routines represent the focal *
|
|
* points from which DOS begins processing information. It *
|
|
* therefore seems logical that the novice should launch his trek *
|
|
* into DOS from these routines. However, the cold- and warm- *
|
|
* start routines are difficult to understand because: *
|
|
* 1) Program execution bounces back and forth between DOS, *
|
|
* BASIC and monitor ROM. *
|
|
* 2) Both the cold- and warmstart routines are riddled with *
|
|
* references to an obscure version of Applesoft that most *
|
|
* people don't even realize exits. *
|
|
* 3) The DOS coldstart routine uses part of the warmstart *
|
|
* routine. In order to distinguish between these two *
|
|
* execution patterns, it is important to pay close *
|
|
* attention to the condition of the status register and *
|
|
* several different flags. *
|
|
* *
|
|
* ABOUT PROGRAM EXECUTION AND THE I/O HOOKS. *
|
|
* The interconnection between DOS, BASIC and monitor ROM is *
|
|
* accomplished by DOS's control over the input (KSW, $36,$37) *
|
|
* and output (CSW, $38,$39) hooks. (These hooks are collectively*
|
|
* referred to as the I/O hooks, the KSW/CSW hooks or the *
|
|
* keyboard/character switches.) In order to understand how DOS *
|
|
* controls these hooks, lets first see what happens when DOS is *
|
|
* NOT present: *
|
|
* - Ordinarily, data output flows through a monitor ROM routine *
|
|
* called "COUT" ($FDED). COUT contains a "JMP (CSW)"instruc- *
|
|
* tion. CSW points to the address of the peripheral to which *
|
|
* output should be sent. For instance, if output is destined *
|
|
* for the screen, CSW points to a monitor routine called *
|
|
* "COUT1" ($FDF0). After COUT1 does some homework, it sends *
|
|
* the character to the screen. Similarly, input normally *
|
|
* flows through the "RDKEY" ($FD0C) routine located in monitor *
|
|
* ROM. This routine contains a "JMP (KSW)" instruction. KSW *
|
|
* normally points to the monitor routine known as "KEYIN" *
|
|
* ($FD1D). KEYIN accepts input from the keyboard. *
|
|
* Now, let's put DOS back into the picture: *
|
|
* - When a coldstart is done, the INITIOHK ($A851) routine in *
|
|
* DOS initializes the I/O hooks to point to DOS's own input *
|
|
* (INPTINCP, $9E81) and output (OPUTINCP, $9E8D) handlers. *
|
|
* Therefore, when DOS is up, any routine that requests input *
|
|
* or output, must go through DOS's own I/O handlers to be *
|
|
* screened. The I/O handlers decide whether the input is to *
|
|
* be taken from the keyboard or the disk and whether output *
|
|
* should be sent to the screen, the disk, the printer or any *
|
|
* other output device. For example, let's assume that we are *
|
|
* running a BASIC program that calls for a character to be *
|
|
* printed on the screen. When BASIC's "PRINT" statement is *
|
|
* encountered, execution flows to the "JMP (CSW)" instruction *
|
|
* in the monitor at COUT ($FDED). Because the output hook *
|
|
* (CSW) points to DOS's output handler, execution flows to *
|
|
* OPUTINCP ($9E8D). OPUTINCP looks at the command line and *
|
|
* discovers that the character is to be sent to the screen. *
|
|
* It then calls PREP4DOS ($9ED1) to repoint the output hook at *
|
|
* the true output handler (COUT1, $FDF0) and JSR's to COUT1. *
|
|
* After COUT1 puts the character on the screen, execution *
|
|
* returns to DOS. DOS does some homework and then execution *
|
|
* flows back to BASIC. Before DOS is exited however, it again *
|
|
* calls the INITIOHK routine to reset the I/O hooks to point *
|
|
* at DOS'S own I/O handlers. *
|
|
* In otherwords, DOS acts like and omnipotent peeping Tom. He *
|
|
* screens all input and output and then takes whatever action he *
|
|
* deems appropriate. *
|
|
* *
|
|
* PARLEZ VOUS APPLESOFT? *
|
|
* The first three models of Apple II computers were based *
|
|
* on two different versions of ROM. Old Apple II's contained *
|
|
* Integer basic in ROM whereas the newer Apple II+/IIe's were *
|
|
* built with Applesoft basic in ROM. In order to accommodate *
|
|
* both types of machines and their hapless programmers, Apple *
|
|
* made the DOS Master disk bilingual. When you boot with this *
|
|
* disk, DOS determines what kind of machine you're using and *
|
|
* what language to load on the RAM card. For example, if you *
|
|
* are using a II+ or IIe, the sytem master disk automatically *
|
|
* runs the "HELLO" program. The "HELLO" program then loads a *
|
|
* file called "INTBASIC" onto the RAM card. (INTBASIC is a *
|
|
* binary file which represents an image of the Integer basic *
|
|
* language.) Similarly, if you're using an old Apple II *
|
|
* machine, the sytem master will run an Integer program *
|
|
* (confusingly called, "APPLESOFT") which loads a file called *
|
|
* "FPBASIC" onto the language card. (FPBASIC is a binary file *
|
|
* which represents an image of Applesoft Floating Point Basic.) *
|
|
* Because this ram-resident version of Applesoft has gone *
|
|
* through several evolutionary stages, it is referred to in the *
|
|
* literature by several different names: disk-based Applesoft, *
|
|
* Applesoft RAM, cassette Applesoft, RAM Applesoft and A(RAM). *
|
|
* Therefore, because the language card can contain a *
|
|
* different language than the motherboard, the cold- and warm- *
|
|
* start routines must determine not only which language is *
|
|
* presently active, but also if the active language is on the *
|
|
* card or motherboard. *
|
|
* *
|
|
* FLAGS AND EXECUTION PATTERNS. *
|
|
* The status register is used to distinguish between the *
|
|
* cold- and warmstart execution patterns. In some cases (ex. *
|
|
* CMWRMCLD,$9DD1), the carry flag is used to determine if a *
|
|
* cold- or warmstart is being executed. However, in other cases *
|
|
* (ex. OPUTINCP, $9E8D and INPTINCPT, $9E81), a specific memory *
|
|
* location is used as a flag. Because several flags appear to *
|
|
* have similar connotations but are set and tested at different *
|
|
* times, one must keep close tabs on the different flag *
|
|
* conditions: *
|
|
* (AA51) *
|
|
* CONDNFLG = I/O condition flag. *
|
|
* = $00 = warmstart. *
|
|
* = $01 = reading a file. *
|
|
* = $C0 = using A(RAM). *
|
|
* (AA52) *
|
|
* OPUTCOND = character output condition flag. *
|
|
* = $00 = evaluate start of input line. *
|
|
* = $01 = got a DOS control character, so collect *
|
|
* the DOS command. *
|
|
* = $02 = not a DOS command, so just print a <cr> *
|
|
* and return to the caller. *
|
|
* = $03 = get ready to process an INPUT statement. *
|
|
* = $04 = writing data to the disk. *
|
|
* = $05 = evaluate the first char of the data line *
|
|
* read from the disk. *
|
|
* = $06 = ignore a question mark prompt & reset to *
|
|
* condition 0. *
|
|
* (AAB3) *
|
|
* EXECFLAG = non-zero value (actually first char of the *
|
|
* name of the exec file) = presently EXECing. *
|
|
* = $00 = not EXECing a file. *
|
|
* (AAB6) *
|
|
* ACTBSFLG = active basic flag. *
|
|
* = $00 = integer. *
|
|
* = $40 = A(ROM). *
|
|
* = $80 = A(RAM). *
|
|
* (AAB7) *
|
|
* RUNTRUPT = run intercept flag. *
|
|
* = $00 = RUN command was NOT interrupted. *
|
|
* = $40 = RUN command was interrupted to load *
|
|
* a file when using A(ROM). *
|
|
* = $80 = RUN command was interrupted to load *
|
|
* a file when using A(RAM). *
|
|
* (E000) *
|
|
* BASICCLD = BASIC's coldstart routine. *
|
|
* (First byte distinguishes type of ROM used.) *
|
|
* = $20 = opcode for "JSR", denotes Integer. *
|
|
* = $40 = opcode for "JMP", denotes A(ROM). *
|
|
* *
|
|
* To help keep things in perspective, the general features *
|
|
* of the cold- and warmstart routines are described below: *
|
|
* *
|
|
* COLDSTART - determine what language & ROM is being used *
|
|
* and fill in the active basic entry point *
|
|
* vector table accordingly. *
|
|
* - reset the I/O hooks so that DOS can intercept *
|
|
* all input & output. *
|
|
* - simulate a "NOMON" command. *
|
|
* - rebuild the DOS buffers (resetting HIMEM, *
|
|
* discarding strings and wiping out the prgm). *
|
|
* - print a prompt and wait for input. *
|
|
* WARMSTART - reset the language card to the language used *
|
|
* when DOS was last cold started. *
|
|
* - reset the I/O hooks so DOS can intercept all *
|
|
* input and output. *
|
|
* - simulate a "NOMON command. *
|
|
* - (note that the program and variables are left *
|
|
* intact.) *
|
|
* *
|
|
*================================================================*
|
|
|
|
|
|
NOTE: THE FOLLOWING DISASSEMBLY IS INCOMPLETE. It does not
|
|
contain all possible ramifications associated with the
|
|
warmstart routine.
|
|
|
|
* DOS's warmstart routine.
|
|
|
|
(9DBF)
|
|
DOSWARM LDA ACTBSFLG ;See which language is up.
|
|
(9DC2) BNE CKBASIC ;Branch if A(ROM), #$40 or A(RAM), #$80.
|
|
|
|
* Integer was up.
|
|
(9DC4) LDA #$20 ;(a) = opcode for "JSR" instruction.
|
|
(9DC6) BNE DTRMNBSC ;ALWAYS.
|
|
|
|
* Active basic flag denoted that a
|
|
* version of Applesoft was active,
|
|
* so now check if dealing with
|
|
* A(RAM) or A(ROM).
|
|
(9DC8)
|
|
CKBASIC ASL ;Multiply code times 2.
|
|
(9DC9) BPL FORWARM ;Branch if A(RAM) (ie. A(RAM) yeilds
|
|
;$40 * 2 = $80 & A(ROM) yeilds $80 * 2 = $00.)
|
|
|
|
* Using A(ROM).
|
|
(9DCB) LDA #$4C ;(a) = opcode for "JMP" instruction.
|
|
DTRMNBSC JSR SETROM ;Select the desired basic.
|
|
(9DCD)
|
|
|
|
* Test card or motherboard to insure that the
|
|
* device containing the ROM version we want is
|
|
* selected. BASICCLD ($E000) contains a "JMP"
|
|
* or a "JSR" instruction if we are dealing with
|
|
* FP or INTEGER ROM respectively.
|
|
(A5B2)
|
|
SETROM CMP BASICCLD ;Test card or motherboard. That is, test
|
|
;whichever device is presently selected.
|
|
(A5B5) BEQ DVICERTN ;The language wanted is resident on the
|
|
;present device.
|
|
|
|
* The language wanted was not on the device
|
|
* selected, so specifically test the card
|
|
* in slot 0. NOTE: We could change the
|
|
* "$C080" to "$Cs80" to enable the card to
|
|
* be located in a different slot (s = slot #).
|
|
(A5B7) STA $C080 ;Read enable slot 0.
|
|
CMP BASICCLD ;Check the identifying byte.
|
|
(A5BD) BEQ DVICERTN ;Branch if the ROM language we wanted
|
|
;is on the card.
|
|
|
|
* ROM version wanted was not on the card.
|
|
* However, we may have just tested the card
|
|
* twice, so now specifically test the motherboard.
|
|
(A5BF) STA $C081 ;Test the motherboard.
|
|
CMP BASICCLD ;Check the identifying byte.
|
|
DVICERTN RTS ;Exit with switches pointing at the last
|
|
(A5C5) ;device tested. If the desired language is
|
|
;present, the switches are left positioned
|
|
;correctly.
|
|
|
|
(9DD0)
|
|
FORWARM CLC ;(c) = 0, signal for warmstart.
|
|
CMWRMCLD PHP ;Save (c) denoting if warm or cold starting.
|
|
(9DD2) JSR INITIOHK ;Initialize the I/O hooks.
|
|
|
|
* Initialize the I/O hooks so that DOS intercepts
|
|
* all input & output. For instance, if a routine
|
|
* encounters a "COUT JMP (CSW)", then execution will
|
|
* actually flow to DOS's output routine (OPUTINCP,
|
|
* $9EBD). Similarly, any routine that refers to
|
|
* "RDKEY JMP (KSW)" will actually jump to DOS's
|
|
* input routine (INPTINCP, $9E81).
|
|
*
|
|
* The true (ie. normal) hooks are saved, ex:
|
|
* KSW: KEYIN --> KSWTRUE: KEYIN.
|
|
* CSW: COUT1 --> CSWTRUE: COUT1.
|
|
* The intercepts are then set as follows:
|
|
* ADINPTCP: INPTINCP --> KSW: INPTINCP.
|
|
* ADOPUTCP: OPUTINCP --> CSW: OPUTINCP.
|
|
|
|
* Check if the input hook needs to be reset.
|
|
(A851)
|
|
INITIOHK LDA KSW+1
|
|
CMP ADINPTCP+1
|
|
(A856) BEQ CKOUTHK ;Input hook already points to DOS's
|
|
;input handler, so go check output hook.
|
|
|
|
* Reset the input hook to point to DOS.
|
|
(A858) STA KSWTRUE+1 ;KSW: KEYIN --> KSWTRUE: KEYIN.
|
|
LDA KSW
|
|
STA KSWTRUE
|
|
LDA ADINPTCP ;ADINPTCP: INPTINCP --> KSW: INPTINCP.
|
|
STA KSW
|
|
LDA ADINPTCP+1
|
|
(A868) STA KSW+1
|
|
|
|
* Check if the output hook needs to be reset.
|
|
(A86A)
|
|
CKOUTHK LDA CSW+1
|
|
CMP ADOPUTCP+1
|
|
(A86F) BEQ SETHKRTN ;Output hook already points to DOS's
|
|
;output handler, so go exit.
|
|
|
|
* Reset the output hook to point to DOS.
|
|
(A871) STA CSWTRUE+1 ;CSW: COUT1 --> CSWTRUE: COUT1.
|
|
LDA CSW
|
|
STA CSWTRUE
|
|
LDA ADOPUTCP ;ADOPUTCP: OPUTINCP --> CSW: OPUTINCP.
|
|
STA CSW
|
|
LDA ADOPUTCP+1
|
|
STA CSW+1
|
|
SETHKRTN RTS
|
|
(A883)
|
|
|
|
(9DD5) LDA #0
|
|
(9DD7) STA CIOCUMUL ;Simulate a "NOMON" command. Note, we can
|
|
;NOP out this instruction to defeat the
|
|
;"NOMONCIO" during warm- or coldstarts.
|
|
(9DDA) STA OPUTCOND ;SET CONDITION 0.
|
|
PLP ;Get status back off the stack.
|
|
ROR ;Use it to set CONDNFLG=$00 for warmstart
|
|
STA CONDNFLG ;or CONDNFLG=$80 for coldstart.
|
|
(9DE2) BMI LANGCOLD ;Branch if doing coldstart.
|
|
|
|
* Doing a warmstart.
|
|
(9DE4)
|
|
LANGWARM JMP (TOWRMVEC) ;Jumps to BASIC's warmstart routine
|
|
------------ ;(RESTART) at $D43C.
|
|
|
|
* NOTE: YOU ARE LEAVING THE COMFORTABLE WORLD
|
|
* OF DOS AND ENTERING THE MURKY REALM OF BASIC.
|
|
|
|
* BASIC's warmstart routine.
|
|
|
|
* GO THROUGH A MILLION STEPS TO PRINT
|
|
* A CARRIAGE RETURN.
|
|
(D43C)
|
|
RESTART JSR CRDO
|
|
|
|
(DAFB)
|
|
CRDO LDA #$0D ;Positive ASCII for <cr>.
|
|
(DAFD) JSR OUTDO
|
|
|
|
(DB5C)
|
|
OUTDO ORA #$80 ;Convert to neg ASCII.
|
|
CMP #" " ;Is it a ctrl char?
|
|
BCC GODOPUT ;Branch if ctrl char.
|
|
ORA FLSHMSK ;$40 for FLASH, $00 for INVERSE or NORMAL.
|
|
GODOPUT JSR COUT ;Go to the output handling routine.
|
|
(DB64)
|
|
|
|
(FDED)
|
|
COUT JMP (CSW)
|
|
------------
|
|
|
|
* DOS's output intercept routine.
|
|
(9EBD)
|
|
OPUTINCP JSR PREP4DOS
|
|
|
|
* Prepare for processing by DOS.
|
|
(9ED1)
|
|
PREP4DOS STA ASAVED ;Save (a), (y) & (x)
|
|
STX XSAVED ;registers.
|
|
STY YSAVED
|
|
TSX ;Adjust stack ptr &
|
|
INX ;save it so when we
|
|
INX ;later restore it &
|
|
(9EDD) STX STKSAVED ;then hit an "RTS"
|
|
;we will return to
|
|
;the ROUTINE THAT
|
|
;CALLED THE ROUTINE
|
|
;THAT CONTAINED THE
|
|
;"JSR SETUP".
|
|
;(In this case, set
|
|
;saved stack ptr to
|
|
;return to $DB67.)
|
|
|
|
* Handy entry point frequently
|
|
* used by assembly language
|
|
* programmers to disconnect
|
|
* DOS completely.
|
|
(9EE0)
|
|
UNCONDOS LDX #3
|
|
SETRUHKS LDA CSWTRUE,X ;Restore the I/O
|
|
STA CSW,X ;hooks 2 pt 2 the
|
|
DEX ;true I/O handlers.
|
|
BPL SETRUHKS ;4 bytes to move
|
|
(9EEA) RTS ;(0 to 3).
|
|
|
|
* Use current OPUTCOND value to index table containing
|
|
* address of output condition handlers. Do a "stack jump"
|
|
* to the appropriate condition handler entry point.
|
|
(9EC0) LDA OPUTCOND
|
|
ASL ;Times 2 cause 2 bytes/address.
|
|
TAX ;Set (x) to index tbl of entry pt addrs.
|
|
LDA OUTHNDTB+1,X ;Put adr of output handler on stack
|
|
PHA ;(hi byte first) and then do a "stack jump"
|
|
LDA OUTHNDTB,X ;to the appropriate entry point.
|
|
PHA
|
|
LDA ASAVED ;Get char to be printed.
|
|
(9ED0) RTS ;Execute the "stack jump".
|
|
|
|
.
|
|
.
|
|
STACK JUMP TO OPUTHDL0
|
|
.
|
|
.
|
|
* Output handler 0.
|
|
* (Evaluate start of line.)
|
|
(9EEB)
|
|
OPUTHDL0 LDX RUNTRUPT ;Was a RUN interrupted?
|
|
(9EEE) BEQ NONTRUPT ;Branch if not.
|
|
|
|
* File not being read.
|
|
(9EF3)
|
|
NONTRUPT LDX CONDNFLG ;Are we doing a warmstart ($00),
|
|
;coldstart ($80), using A(RAM) ($C0)
|
|
;or doing a READ ($01)?
|
|
(9EF6) BEQ SETIGNOR ;Branch if warmstarting.
|
|
|
|
* Doing a warmstart so set condition 2 as a
|
|
* default to signal that non-DOS commands
|
|
* should be ignored.
|
|
(9F00)
|
|
SETIGNOR LDX #2 ;SET CONDITION 2.
|
|
STX OPUTCOND
|
|
CMP DCTRLCHR ;Is the char = DOS's control character?
|
|
(9F08) BNE OPUTHDL2 ;No, it is a <cr> so branch.
|
|
|
|
* Output handler 2.
|
|
* (Ignore non-DOS commands.)
|
|
(9F23)
|
|
OPUTHDL2 CMP #$8D ;Is char a <rtn>?
|
|
BNE DSPLYALL ;Yes - fall thru.
|
|
SET2EVAL LDX #0 ;SET CONDITION 0 - evaluate start
|
|
STX OPUTCOND ;of line.
|
|
(9F2C) JMP DSPLYALL ;Go display char unconditionally.
|
|
------------
|
|
|
|
* Display the char.
|
|
(9FA4)
|
|
DSPLYALL JSR RESTOREG
|
|
|
|
* Restore (a), (y) & (x) registers.
|
|
(9FBA)
|
|
RESTOREG LDA ASAVED
|
|
LDY YSAVED
|
|
LDX XSAVED
|
|
SEC ;Why?????
|
|
(9FC4) RTS
|
|
|
|
(9FA7) JSR GODSPLY
|
|
|
|
* PRINT A <CR> THROUGH THE TRUE
|
|
* OUTPUT HANDLER.
|
|
(9FC5)
|
|
GODSPLY JMP (CSW)
|
|
------------
|
|
|
|
(FDF0)
|
|
COUT1 .
|
|
.
|
|
(See dis'mbly in APPLE II REFERENCE MANUAL.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
* Save registers.
|
|
(9FAA) STA ASAVED ;Save (a), (y) & (x) registers.
|
|
STY YSAVED
|
|
(9FB0) STX XSAVED
|
|
|
|
* Reset hooks & stack pointer.
|
|
(9FB3)
|
|
DOSEXIT JSR INITIOHK ;Reset DOS hooks.
|
|
|
|
* Initialize the I/O hooks so that DOS
|
|
* intercepts all input & output.
|
|
(A851)
|
|
INITIOHK .
|
|
.
|
|
(See dis'mbly above.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
* Reset stack pointer & save registers.
|
|
(9FB6) LDX STKSAVED ;Retrieve the saved stack pointer value
|
|
TXS ;& reset the stack to return to caller.
|
|
RESTOREG LDA ASAVED ;Restore (a), (y) & (x) registers.
|
|
LDY YSAVED
|
|
LDX XSAVED
|
|
SEC ;Return to routine that called routine
|
|
(9FC4) RTS ;that contained "JSR PREP4DOS" instruc.
|
|
|
|
* Convert char back to positive ASCII
|
|
* so we can keep Applesoft happy.
|
|
(DB67) AND #$7F ;Convert char.
|
|
PHA ;Save it on the stack.
|
|
LDA SPEEDFLG ;Delay in accordance with speed setting.
|
|
(DB6C) JSR WAIT
|
|
|
|
* Monitor ROM's main delay routine.
|
|
* Delay z number of cycles based on
|
|
* the formula:
|
|
* z = ((5 * a^2) + (27 * a) + 26) / 2
|
|
* where a = value in accumulator on entry.
|
|
(FCA8)
|
|
WAIT SEC ;Prepare for subtraction.
|
|
WAIT2 PHA ;Save (a) on the stack.
|
|
WAIT3 SBC #1 ;Keep on reducing (a)
|
|
BNE WAIT3 ;until it equals zero.
|
|
PLA ;Get original val of (a) off stack.
|
|
SBC #1 ;Reduce original (a) down to 0 again.
|
|
BNE WAIT2
|
|
(FCB3) RTS
|
|
|
|
(DB6F) PLA ;Get saved positive ASCII char back from stack.
|
|
(DB70) RTS
|
|
|
|
(DB00) EOR #$FF ;No reason for this???
|
|
(DB02) RTS
|
|
|
|
* PRINT THE APPLESOFT PROMPT through
|
|
* Basic, DOS's output handler (OPUTINCP)
|
|
* and the monitor. THEN, INTERCEPT INPUT
|
|
* through DOS's input handler (INPTINCP).
|
|
(D43F) LDX #$DD ;RH brackett for Applesoft prompt.
|
|
(D441) JSR INLINPL2
|
|
|
|
(D52E)
|
|
INLINPL2 STX PROMPT
|
|
(D530) JSR GETLN
|
|
|
|
* Get a line of input.
|
|
(FD6A)
|
|
GETLN LDA PROMPT ;Print prompt.
|
|
(FD6C) JSR COUT
|
|
|
|
(FDED)
|
|
COUT JMP (CSW) ;Output hook pts to DOS's output handler.
|
|
------------
|
|
|
|
* DOS's output intercept routine.
|
|
(9EBD)
|
|
OPUTINCP JSR PREP4DOS
|
|
|
|
(9ED1)
|
|
PREP4DOS STA ASAVED ;Save (a), (y) & (x)
|
|
STX XSAVED ;registers.
|
|
STY YSAVED
|
|
TSX ;Adjust stk ptr and
|
|
INX ;save it so that
|
|
INX ;when we later
|
|
(9EDD) STX STKSAVED ;restore it and hit
|
|
;an "RTS", we can
|
|
;return to routine
|
|
;that called the
|
|
;routine that
|
|
;contained the
|
|
;"JSR PREP4DOS"
|
|
;instruction.
|
|
;(In this case, set
|
|
;saved stack ptr to
|
|
;return to $FD6F.)
|
|
|
|
* Restore the I/O hooks to point to the
|
|
* true I/O handlers, ex:
|
|
* KSWTRUE: KEYIN --> KSW: KEYIN.
|
|
* CSWTRUE: COUT1 --> CSW: COUT1.
|
|
(9EE0)
|
|
UNCONDOS LDX #3
|
|
SETRUHKS LDA CSWTRUE,X
|
|
STA CSW,X
|
|
DEX
|
|
BPL SETRUHKS ; 4 bytes to move
|
|
(9EEA) RTS ;(0 to 3).
|
|
|
|
* Use current OPUTCOND value to index table containing
|
|
* address of output condition handlers. Do a "stack jump"
|
|
* to the appropriate condition handler entry point.
|
|
(9EC0) LDA OPUTCOND
|
|
ASL ;Times 2 cause 2 bytes/address.
|
|
TAX ;Set (x) to index table of addresses.
|
|
LDA OUTHNDTB+1,X ;Put adr of output handler on stack
|
|
PHA ;(hi byte first) and then do a "stack jump"
|
|
LDA OUTHNDTB,X ;to the appropriate entry point.
|
|
PHA
|
|
LDA ASAVED ;Get char to be printed.
|
|
(9ED0) RTS ;Execute the "stack jump".
|
|
|
|
.
|
|
.
|
|
STACK JUMP TO OPUTHDL0
|
|
.
|
|
.
|
|
* Output handler 0.
|
|
* (Evaluate start of line.)
|
|
(9EEB)
|
|
OPUTHDL0 LDX RUNTRUPT ;Was a RUN interrupted?
|
|
(9EEE) BEQ NONTRUPT ;Branch if not.
|
|
|
|
* File not being read.
|
|
(9EF3)
|
|
NONTRUPT LDX CONDNFLG ;Are we doing a warmstart ($00),
|
|
;coldstart ($80), using A(RAM) ($C0)
|
|
;or doing a read ($01)?
|
|
(9EF6) BEQ SETIGNOR ;Branch if warmstarting.
|
|
|
|
* Warmstarting, so set condition 2.
|
|
(9F00)
|
|
SETIGNOR LDX #2 ;SET CONDITION 2 as a default to signal
|
|
STX OPUTCOND ;that we should ignore non-DOS commands.
|
|
CMP DCTRLCHR ;Is char = DOS's ctrl char?
|
|
(9F08) BNE OPUTHDL2 ;No, it is a prompt so take branch.
|
|
|
|
* Output handler 2.
|
|
* (Ignore non-DOS commands.)
|
|
(9F23)
|
|
OPUTHDL2 CMP #$8D ;<rtn>?
|
|
(9F25) BNE DSPLYALL ;No, isn't a <cr> so take branch.
|
|
|
|
* Display the char.
|
|
(9FA4)
|
|
DSPLYALL JSR RESTOREG
|
|
|
|
* Restore (a), (y) & (x) registers.
|
|
(9FBA)
|
|
RESTOREG LDA ASAVED
|
|
LDY YSAVED
|
|
LDX XSAVED
|
|
SEC ;Why?????
|
|
(9FC4) RTS
|
|
|
|
(9FA7) JSR GODSPLY
|
|
|
|
(9FC5)
|
|
GODSPLY JMP (CSW)
|
|
------------
|
|
|
|
* PRINT APPLESOFT PROMPT through
|
|
* the true output handler.
|
|
(FDF0)
|
|
COUT1 .
|
|
.
|
|
- print char thru true output handler.
|
|
(See dis'mbly in APPLE II REFERENCE MANUAL.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
* Save registers & reset hooks.
|
|
(9FAA) STA ASAVED ;Save (a), (y) & (x) registers.
|
|
STY YSAVED
|
|
(9FB0) STX XSAVED
|
|
|
|
* Routine to exit DOS.
|
|
(9FB3)
|
|
DOSEXIT JSR INITIOHK
|
|
|
|
* Initialize the I/O hooks so that DOS
|
|
* intercepts all input & output.
|
|
(A851)
|
|
INITIOHK .
|
|
.
|
|
(See dis'mbly given above.)
|
|
.
|
|
.
|
|
(9FC4) (RTS)
|
|
|
|
(9FB6) LDX STKSAVED ;Retrieve the saved stack pointer val
|
|
TXS ;& reset the stack to return to caller.
|
|
RESTOREG LDA ASAVED ;Restore (a), (y) & (x) registers.
|
|
LDY YSAVED
|
|
LDX XSAVED
|
|
SEC ;Return to the routine that called the
|
|
(9FC4) RTS ;routine that contained the "JSR PREP4DOS"
|
|
;instruction.
|
|
|
|
*******************************
|
|
* *
|
|
* GET A SINGLE BYTE OF INPUT.
|
|
* *
|
|
*******************************
|
|
(FD6F) LDX #1
|
|
BCKSPC TXA ;Force fall thru to next instruction.
|
|
BEQ GETLNZ
|
|
DEX ;Initialize (x) = 0 as index to input buf.
|
|
NXTCHAR JSR RDCHAR
|
|
(FD75)
|
|
|
|
* Routine to read an input byte.
|
|
(FD35)
|
|
RDCHAR JSR RDKEY
|
|
|
|
(FD0C)
|
|
RDKEY LDY CH ;Get horiz cursor
|
|
;pos'n 4 nxt char.
|
|
(FD0E) LDA (BASL),Y ;Pick up char in next
|
|
(FD10) PHA ;screen pos'n & save
|
|
;it on the stack.
|
|
(FD11) AND #$3F ;Convert char to
|
|
ORA #$40 ;flashing.
|
|
(FD15) STA (BASL),Y ;Put flashing char
|
|
;on scrn to serve
|
|
;as cursor.
|
|
(FD17) PLA ;Get char back that
|
|
;cursor is replacing.
|
|
;(Need it in case do
|
|
;bkspc or -> and
|
|
;want to reinstate
|
|
;orig char on scrn).
|
|
(FD18) JMP (KSW) ;Input hook still
|
|
------------ ;pointing to DOS.
|
|
|
|
************** NOTE *******************
|
|
* In order to keep things simple, the *
|
|
* following disassembly assumes that: *
|
|
* 1) we are not EXECing or RUNning a *
|
|
* program. *
|
|
* 2) no control chars are input from *
|
|
* the keyboard. *
|
|
***************************************
|
|
|
|
* DOS intercepts input.
|
|
(9E81)
|
|
INPTINCP JSR PREP4DOS ;Save regs & stk ptr
|
|
|
|
* Adjust & save stk
|
|
* ptr so can later
|
|
* return to $FD38.
|
|
* Pt hks at true
|
|
* I/O handlers.
|
|
(9ED1)
|
|
PREP4DOS .
|
|
.
|
|
(See dis'mbly
|
|
above.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
(9E84) LDA CONDNFLG ;Test condition.
|
|
(9E87) BEQ INPUTWRM ;Branch if warmstart.
|
|
|
|
* Using warmstart condition.
|
|
* At this point, both CONDNFLG
|
|
* & OPUTCOND = 0 for both
|
|
* cold- and warmstarts.
|
|
(9E9E)
|
|
INPUTWRM LDA EXECFLAG ;Are we execing?
|
|
(9EA1) BEQ INPTNOXC ;No
|
|
|
|
(9EA6)
|
|
INPTNOXC LDA #3 ;SET CONDITION 3 to
|
|
(9EA8) STA OPUTCOND ;to signal that we
|
|
;want to process
|
|
;input information.
|
|
|
|
(9EAB) JSR RESTOREG
|
|
|
|
* Restore regs.
|
|
(9FBA)
|
|
RESTOREG LDA ASAVED
|
|
LDY YSAVED
|
|
LDX XSAVED
|
|
SEC
|
|
(9FC4) RTS
|
|
|
|
(9EAE) JSR TOTRUIN
|
|
|
|
* Go to the true
|
|
* input handler.
|
|
(9EBA)
|
|
TOTRUIN JMP (KSW)
|
|
------------
|
|
************** N O T E ***************
|
|
* * * Increment the
|
|
* You are here when DOS is up, you're * * random # locs
|
|
* not running a program & THE COMPUTER * * & get code of
|
|
* IS BLINKING AT YOU WHILE WAITING FOR * * the key pressed.
|
|
* INPUT FROM THE KEYBOARD -----------------------------------------------------------------------> (FD1D)
|
|
* * KEYIN INC RNDL
|
|
**************************************** BNE KEYIN2
|
|
INC RNDH
|
|
KEYIN2 BIT KBD
|
|
BPL KEYIN
|
|
STA (BASL),Y
|
|
LDA KBD
|
|
BIT KBDSTRB
|
|
(FD2E) RTS
|
|
|
|
(9EB1) STA ASAVED ;SAVE CHAR JUST READ.
|
|
(9EB4) STX XSAVED ;SAVE INDEX TO INPUT
|
|
;BUFFER.
|
|
(9EB7) JMP DOSEXIT
|
|
------------
|
|
|
|
* Routine to exit DOS.
|
|
(9FB3)
|
|
DOSEXIT JSR INITIOHK
|
|
|
|
* Initialize I/O hks
|
|
* so DOS intercepts
|
|
* all input & output.
|
|
(A851)
|
|
INITIOHK .
|
|
.
|
|
(See dis'mbly above.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
(9FB6) LDX STKSAVED ;Restore stk pointer.
|
|
TXS
|
|
RESTOREG LDA ASAVED ;Restore registers.
|
|
LDY YSAVED
|
|
LDX XSAVED
|
|
SEC ;Why?????
|
|
(9FC4) RTS ;RETURN TO THE ROUTINE
|
|
;THAT CALLED THE
|
|
;ROUTINE THAT
|
|
;CONTAINED THE
|
|
;"JSR PREP4DOS"
|
|
;INSTRUCTION.
|
|
|
|
(FD38) CMP #$9B ;Was the escape key pressed?
|
|
BEQ ESC ;Yes - go handle escape.
|
|
(FD3C) RTS
|
|
|
|
(FD78) CMP #$95 ;Was char a ctrl-U (right arrow)?
|
|
BNE CAPTST ;No.
|
|
(FD7C) LDA (BASL),Y ;Yes - prepare to put the original image
|
|
; of char in the next screen pos'n
|
|
(FD7E) ; back on the screen.
|
|
CAPTST CMP #$E0 ;Was char lower case?
|
|
BCC ADDINP ;No - go put new char in the input buffer.
|
|
AND #$DF ;Convert lower case to upper case.
|
|
ADDINP STA BUFF200,X ;Put char in the input buffer.
|
|
CMP #$8D ;Was char input a <cr>?
|
|
(FD89) BNE NOTCR ;Branch if char wasn't a <cr>.
|
|
|
|
* A <cr> was typed in from the keyboard
|
|
* denoting the end of input.
|
|
(FD8B) JSR CLREOL
|
|
|
|
* Clear to end of line.
|
|
(FC9C)
|
|
CLREOL LDY CH ;(y) = next char's screen position.
|
|
CLEOLZ LDA #" " ;(a) = space to blank out line.
|
|
CLEOL2 STA (BASL),Y ;Put blanks on screen from the next
|
|
INY ;char position to the end of the screen
|
|
CPY WNDWDTH ;line (as determined by WNDWDTH).
|
|
BCC CLEOL2
|
|
(FCA7) RTS
|
|
|
|
(FD8E)
|
|
CROUT LDA #$8D ;Set (a) = carriage return.
|
|
(FD90) BNE COUT ;ALWAYS.
|
|
|
|
(FDED)
|
|
COUT JMP (CSW)
|
|
------------
|
|
|
|
* DOS's output intercept routine.
|
|
(9EBD)
|
|
OPUTINCP JSR PREP4DOS
|
|
|
|
* Prepare for processing by DOS.
|
|
*
|
|
* Save the registers & stack pointer.
|
|
* Restore the I/O hooks to point to the
|
|
* true I/O handlers, ex:
|
|
* KSWTRUE: KEYIN --> KSW: KEYIN.
|
|
* CSWTRUE: COUT1 --> CSW: COUT1.
|
|
(9ED1)
|
|
PREP4DOS STA ASAVED ;Save (a), (y) & (x) registers.
|
|
STX XSAVED
|
|
STY YSAVED
|
|
TSX ;Adjust stack ptr & save it so when we
|
|
INX ;later restore it & then hit an "RTS"
|
|
INX ;instruction, we will return to the
|
|
(9EDD) STX STKSAVED ;ROUTINE THAT CALLED THE ROUTINE THAT
|
|
;CONTAINED THE "JSR SETUP" INSTRUCTION.
|
|
;(In this case, set saved stack pointer
|
|
;so we can return to $D533.)
|
|
|
|
* Handy entry point frequently used by
|
|
* assembly language programmers to disconnect
|
|
* DOS completely.
|
|
(9EE0)
|
|
UNCONDOS LDX #3
|
|
SETRUHKS LDA CSWTRUE,X ;Restore the I/O hooks to point
|
|
STA CSW,X ;to the true I/O handlers.
|
|
DEX
|
|
BPL SETRUHKS ;4 bytes to move (0 to 3).
|
|
(9EEA) RTS
|
|
|
|
* Use current OPUTCOND value to index table containing
|
|
* address of output condition handlers. Do a "stack jump"
|
|
* to the appropriate condition handler entry point.
|
|
(9EC0) LDA OPUTCOND
|
|
ASL ;Times 2 cause 2 bytes/address.
|
|
TAX ;Set (x) to index tbl of entry pt addrs.
|
|
LDA OUTHNDTB+1,X ;Put adr of output handler on stack
|
|
PHA ;(hi byte first) and then do a "stack jump"
|
|
LDA OUTHNDTB,X ;to the appropriate entry point.
|
|
PHA
|
|
LDA ASAVED ;Get char to be printed.
|
|
(9ED0) RTS ;Execute the "stack jump".
|
|
|
|
.
|
|
.
|
|
STACK JUMP TO OPUTHDL3
|
|
.
|
|
.
|
|
* Output handler 3.
|
|
* (PROCESS THE INPUT INFORMATION.)
|
|
(9F2F)
|
|
OPUTHDL3 LDX #0 ;SET CONDITION 0 when input ends.
|
|
STX OPUTCOND
|
|
CMP #$8D ;Was char an input-terminating <cr>?
|
|
(9F36) BEQ ASUMIMED ;Yes.
|
|
|
|
(9F3F)
|
|
ASUMIMED PHA ;Save character on the stack.
|
|
(9F40) SEC ;(c) = 1, default condition to assume we
|
|
;are presently in the immediate mode.
|
|
(9F41) LDA EXECFLAG ;Check if we are EXECing.
|
|
BNE TESTMODE ;Branch if we are EXECing.
|
|
(9F46) JSR CKBSCRUN ;Not execing so see if basic is running a
|
|
;program or not.
|
|
|
|
* Check if basic is running a program.
|
|
(A65E)
|
|
CKBSCRUN PHA ;Save (a) on the stack.
|
|
LDA ACTBSFLG ;Check which basic is up.
|
|
(A662) BEQ INTBASIC ;Branch if using integer.
|
|
|
|
* Using Applesoft, so now check the hi byte
|
|
* of the line number to see if in immediate
|
|
* mode or not. If line number > 65288 (ie. $FF
|
|
* in hi byte) then we are in the immediate mode.
|
|
(A664) LDX CURLIN+1 ;Check hi byte of the line number.
|
|
INX ;If $FF --> $00, then number > 65288.
|
|
(A667) BEQ IMEDMODE ;Branch if using immediate mode.
|
|
|
|
* FP appears to be running a program but,
|
|
* maybe CURLIN+1 was zapped, so better
|
|
* also check the prompt.
|
|
(A669) LDX PROMPT
|
|
CPX #$DD ;Applesoft prompt (RH brackett)?
|
|
BEQ IMEDMODE ;Yes - so must be in the immediate mode.
|
|
RUNNING PLA ;Get the saved (a) back from the stack.
|
|
CLC ;Signal that the program is running.
|
|
(A671) RTS
|
|
============
|
|
|
|
(A672)
|
|
INTBASIC LDA RUNMODE ;Check Integer basic's run mode flag.
|
|
(A674) BMI RUNNING ;If negative, then Integer basic is in
|
|
(A676) ;the deferred mode.
|
|
IMEDMODE PLA ;Get saved (a) back from the stack.
|
|
SEC ;Signal that we are in the immediate mode.
|
|
(A678) RTS
|
|
============
|
|
|
|
(9F49)
|
|
TESTMODE PLA ;Retrieve char from the stack.
|
|
(9F4A) BCC TESTEXEC ;Branch if basic is running.
|
|
;(c) = 0 = either basic running.
|
|
;(c) = 1 = immediate mode.
|
|
|
|
* Execing or in immediate mode.
|
|
(9F4C) LDX XSAVED ;Retrieve index to the input buffer.
|
|
(9F4F) JMP PUTINBUF ;Go put char in input buf (condition 1).
|
|
------------
|
|
|
|
* Put char in the input buffer & then
|
|
* go display char or else go parse the
|
|
* command.
|
|
(9F15)
|
|
PUTINBUF STA BUF200,X ;Put char in the input buffer.
|
|
INX ;Kick up index to the next buffer pos'n.
|
|
STX NDX2INBF
|
|
CMP #$8D ;Was char a carriage return?
|
|
BNE DSPLYCMD ;No.
|
|
(9F20) JMP PARSECMD ;Yes - got end of input, so now go
|
|
------------ ; and see if it is a DOS command.
|
|
|
|
* Input character was not a carriage return.
|
|
(FD3D)
|
|
NOTCR LDA INVFLG ;Save current inverse flag on stack.
|
|
PHA
|
|
LDA #$FF ;Set inverse flag to normal.
|
|
STA INVFLG
|
|
LDA BUF200,X ;Get char to be printed.
|
|
(FD47) JSR COUT
|
|
|
|
(FDED)
|
|
COUT JMP (CSW) ;Output hook pts to DOS's output handler.
|
|
------------
|
|
|
|
* DOS's output intercept routine.
|
|
(9EBD)
|
|
OPUTINCP JSR PREP4DOS
|
|
|
|
(9ED1)
|
|
PREP4DOS STA ASAVED ;Save (a), (y) & (x)
|
|
STX XSAVED ;registers.
|
|
STY YSAVED
|
|
TSX ;Adjust stk ptr and
|
|
INX ;save it so that
|
|
INX ;when we later
|
|
(9EDD) STX STKSAVED ;restore it and hit
|
|
;an "RTS", we can
|
|
;return to $FD4A.
|
|
|
|
* Restore the I/O hooks to point to the
|
|
* true I/O handlers, ex:
|
|
* KSWTRUE: KEYIN --> KSW: KEYIN.
|
|
* CSWTRUE: COUT1 --> CSW: COUT1.
|
|
(9EE0)
|
|
UNCONDOS LDX #3
|
|
SETRUHKS LDA CSWTRUE,X
|
|
STA CSW,X
|
|
DEX
|
|
BPL SETRUHKS ; 4 bytes to move
|
|
(9EEA) RTS ;(0 to 3).
|
|
|
|
* Use current OPUTCOND value to index table containing
|
|
* address of output condition handlers. Do a "stack jump"
|
|
* to the appropriate condition handler entry point.
|
|
(9EC0) LDA OPUTCOND
|
|
ASL ;Times 2 cause 2 bytes/address.
|
|
TAX ;Set (x) to index table of addresses.
|
|
LDA OUTHNDTB+1,X ;Put adr of output handler on stack
|
|
PHA ;(hi byte first) and then do a "stack jump"
|
|
LDA OUTHNDTB,X ;to the appropriate entry point.
|
|
PHA
|
|
LDA ASAVED ;Get char to be printed.
|
|
(9ED0) RTS ;Execute the "stack jump".
|
|
|
|
.
|
|
.
|
|
STACK JUMP TO OPUTHDL3
|
|
.
|
|
.
|
|
* Output handler 3.
|
|
* (Process the input information.)
|
|
(9F2F)
|
|
OPUTHDL3 LDX #0 ;SET CONDITION 0 when input ends.
|
|
STX OPUTCOND
|
|
CMP #$8D ;Carriage return?
|
|
(9F36) BEQ ASUMIMED ;Yes.
|
|
|
|
* Char was not a carriage return.
|
|
(9F38)
|
|
TESTEXEC LDA EXECFLAG ;Are we EXECing?
|
|
(9F3B) BEQ DSPLYALL ;No.
|
|
|
|
* Display the char.
|
|
(9FA4)
|
|
DSPLYALL JSR RESTOREG
|
|
|
|
* Restore (a), (y) & (x) registers.
|
|
(9FBA)
|
|
RESTOREG LDA ASAVED
|
|
LDY YSAVED
|
|
LDX XSAVED
|
|
SEC ;Why?????
|
|
(9FC4) RTS
|
|
|
|
(9FA7) JSR GODSPLY
|
|
|
|
(9FC5)
|
|
GODSPLY JMP (CSW)
|
|
------------
|
|
|
|
* PRINT INPUT CHAR THROUGH
|
|
* THE TRUE OUTPUT HANDLER.
|
|
(FDF0)
|
|
COUT1 .
|
|
.
|
|
(See dis'mbly in APPLE II REFERENCE MANUAL.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
* Save registers & reset hooks.
|
|
(9FAA) STA ASAVED ;Save (a), (y) & (x) registers.
|
|
STY YSAVED
|
|
(9FB0) STX XSAVED
|
|
|
|
* Routine to exit DOS.
|
|
(9FB3)
|
|
DOSEXIT JSR INITIOHK
|
|
|
|
* Initialize the I/O hooks so that DOS
|
|
* intercepts all input & output.
|
|
(A851)
|
|
INITIOHK .
|
|
.
|
|
(See dis'mbly given above.)
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
(9FB6) LDX STKSAVED ;Retrieve the saved stack pointer val
|
|
TXS ;& reset the stack to return to caller.
|
|
RESTOREG LDA ASAVED ;Restore (a), (y) & (x) registers.
|
|
LDY YSAVED
|
|
LDX XSAVED
|
|
SEC ;Return to the routine that called the
|
|
(9FC4) RTS ;routine that contained the "JSR PREP4DOS"
|
|
;instruction.
|
|
|
|
(FD4A) PLA ;Restore the original contents of the
|
|
STA INVFLG ;inverse flag.
|
|
LDA BUF200,X ;(a) = char that was input.
|
|
CMP #$88 ;Was char a backspace?
|
|
BEQ BCKSPC ;Yes.
|
|
CMP #$98 ;Was char a ctrl-X (cancel char)?
|
|
BEQ CANCEL ;Yes.
|
|
CPX #$F8 ;Input 249 (0 to 248) chars yet?
|
|
BCC NOTCR1 ;No.
|
|
JSR BELL ;Yes - go ring the warning bell.
|
|
NOTCR1 INX ;Increase the input character counter.
|
|
(FD60) BNE NXTCHAR ;Character counter hasn't wrapped around to
|
|
(FD62) ;zero yet, so go get next char.
|
|
CANCEL . ;Too many chars were input, so go cancel
|
|
. ;the input line.
|
|
.
|
|
============
|
|
|
|
(9FCD)
|
|
PARSECMD .
|
|
.
|
|
************************************
|
|
* - PARSE & EXECUTE THE COMMAND. *
|
|
* - Enter with STKSAVED set to *
|
|
* return to $D533. *
|
|
* - Return with I/O hooks pointing *
|
|
* to DOS's input/output handling *
|
|
* routines. *
|
|
* - Note: The computer ends up in *
|
|
* an infinite loop if a BRUN cmd *
|
|
* was just executed AND if the *
|
|
* binary file performed any *
|
|
* output or input OR if the prgm *
|
|
* returns with MON C in effect. *
|
|
* (See dis'mbly of the BRUN cmd *
|
|
* handler for details.) *
|
|
************************************
|
|
.
|
|
.
|
|
- See disassembly titled "DOSCMDPARSING&PROCESSING".
|
|
.
|
|
.
|
|
(RTS)
|
|
|
|
(D533) CPX #$EF ;240 characters yet (0 to 23)?
|
|
BCC TERMIN8 ;No.
|
|
LDX #$EF ;Yes.
|
|
TERMIN8 LDA #0 ;Put an end-of-line marker (EOL, $00)
|
|
STA BUF200,X ;in the input buffer.
|
|
TXA ;Is (x) = 0?
|
|
(D53F) BEQ NEG8NPUT ;Yes - so just completed a SIMPLE IMMEDIATE
|
|
; MODE DOS COMMAND & have set the first
|
|
; byte in the input buffer to a $00.
|
|
|
|
* No simple immediate mode DOS command present,
|
|
* so if the line contains any DOS commands, they
|
|
* must be in a PRINT program statement or in an
|
|
* immediate mode PRINT statement.
|
|
* for example: 100 D$ = CHR$(4): PRINT D$;"CATALOG"
|
|
* OR
|
|
* D$ = CHR$(4): PRINT D$;"CATALOG"
|
|
* In either case, we are dealing with an Applesoft
|
|
* statement, so strip the hi bit off the characters
|
|
* (ie. convert to positive ASCII to keep Applesoft
|
|
* happy).
|
|
(D541)
|
|
CNVRTPOS LDA BUF200-1,X ;Get the byte in the input buffer.
|
|
AND #$7F ;Strip off the hi bit.
|
|
(D546) STA BUF200-1,X ;Put the positive ASCII char back in
|
|
;the input buffer.
|
|
(D549) DEX ;Reduce the index to the input buffer.
|
|
BNE CNVRTPOS ;When (x) = 0, done stripping.
|
|
NEG8NPUT LDA #0 ;Initialize (a) = 0.
|
|
LDX #<BUF200-1 ;Set (x) = $FF.
|
|
LDY #>BUF200-1 ;Set (y) = $01.
|
|
(D552) RTS
|
|
|
|
(D444) STX TXTPTR ;Set TXTPTR to point 1 byte below the
|
|
STY TXTPTR+1 ;input buf (ie. $1FF) - will increment it later.
|
|
LSR ERRFLG ;Zero out the error flag.
|
|
(D44A) JSR CHRGET ;Get the first byte in the input buffer.
|
|
|
|
* Get a byte from the input buffer.
|
|
* Note: Uses SELF-MODIFYING code.
|
|
* On exit: (a) = char from input buf.
|
|
* (z) = 1 only if ':' (end-of-statement marker, EOS,
|
|
* $3A) or $00 (end-of-line maker, EOL).
|
|
* = 0 for all other values.
|
|
* (c) = 0 only if ASCII number betw'n '0' <----> '9',
|
|
* (ie, $30 ,----> $39).
|
|
* = 1 for all other values.
|
|
|
|
(00B1)
|
|
CHRGET INC TXTPTR ;Modify pointer to input buffer.
|
|
BNE CHRGOT
|
|
(00B5) INC TXTPTR+1
|
|
|
|
(00B7)
|
|
CHRGOT HEX AD ;Actually an absolute "LDA" opcode.
|
|
TXTPTR DS 2 ;Contents modified by INC instructions above.
|
|
(00B8) ;The above three bytes are therefore equivalent
|
|
;to the non-existent instruction: LDA (TXTPTR)
|
|
;which assumes a zero index. (PS. By using self-
|
|
;modifying code, we do the equivalent of an indirect
|
|
;load without having to mess up the y-register.)
|
|
(00BA) CMP ':' ;Is char an EOS ($3A) or greater?
|
|
BCS CHRGTRTN ;Yes
|
|
CMP ' ' ;Space?
|
|
(00C0) BEQ CHRGET ;Yes - ignore spaces.
|
|
|
|
* Play with (a) and exit with (a) intact
|
|
* but (c) and (z) conditioned.
|
|
* Do: (a) - $30 - $D0. That is, do the
|
|
* equivalent to:
|
|
* (a) - $30 + $30 or (a) + $D0 - $D0,
|
|
* because $30 = two's complement of $D0
|
|
* and $D0 = two's complement of $30.
|
|
(00C2) SEC ;Prep for dummy subtraction.
|
|
SBC '0' ;That is: (a) = (a) - $30 or (a) = (a) + $D0
|
|
(00C5) SEC ;Prep for next dummy subtraction (which will
|
|
;reinstate (a) to its original value).
|
|
(00C6) SBC #$D0 ;That is: (a) = (a) - $D0 or (a) = (a) + $30
|
|
;Reinstates (a) to original entry value but
|
|
;conditions (c) and (z).
|
|
CHRGTRTN RTS ;Exit with (a) = orig char.
|
|
(00C8) ; (z) = 0 if EOS (':', $3A)
|
|
; or EOL ($00).
|
|
; (c) = 0 if '0' <----> '9'
|
|
; ($30 <----> $39).
|
|
|
|
(D44D) TAX ;Stick it in (x)
|
|
(D44E) BEQ RESTART ;IF THE FIRST BYTE IS A $00, THEN WE HAVE
|
|
;JUST COMPLETED A SIMPLE IMMEDIATE MODE DOS
|
|
;COMMAND, SO NOW GO BACK TO GET THE NEXT
|
|
;LINE OF INPUT.
|
|
|
|
* Did not just complete a simple immediate mode
|
|
* DOS command. Therefore, if any DOS commands
|
|
* are indeed present, they must be imbedded in
|
|
* an Appplesoft program or else in an immediate
|
|
* mode line.
|
|
.
|
|
.
|
|
- set the immediate mode.
|
|
- if the first character in the input buffer is
|
|
a number, then we must be adding a program line
|
|
so go to the appropriate Applesoft routine.
|
|
- if the first character is not a number, then go
|
|
to Applesoft's parse routine and parse the line
|
|
(ie. tokenize it).
|
|
- after tokenization, check if the trace flag is on
|
|
and then go execute each statement in the line.
|
|
- when a statement requiring input or output is
|
|
encountered, DOS regains control via the I/O
|
|
hooks.
|
|
- eventually, we end up back at the RESTART ($D43C)
|
|
routine waiting for input.
|