****************************************************************** * * * DOS's coldstart 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 exists. * * 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 * * normaly 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 at DOS's own input * * (INPTINCP, $9E8A) 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 an 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 Apples 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 system 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 system 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 * * 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.) * * * *================================================================* * DOS's coldstart routine. * (P.S. Don't confuse with basic's coldstart * routine (BASICCLD, $E000).) (9D84) DOSCOLD LDA IBSLOT ;Slot * 16 from RWTS's IOB table. LSR ;Divide by 16. LSR LSR LSR STA SLOTPRSD ;Put slot in parsed table. LDA IBDRVN ;Drive # from RWTS's IOB. (9D91) STA DRVPRSD ;Put drive in parsed table. * Check which basic is in ROM. (9D94) LDA BASICCLD ;Get identifying byte: $20 = integer EOR #$20 ; $40 = A(ROM). (9D99) BNE ISFPROM ;Branch if FP is in ROM. * Integer basic is active. (9D9B) ISINT STA ACTBSFLG ;Set active basic flag to denote ;integer ($00). * Copy image of INTEGER basic's entry point vector * table to the active entry point vector table. (9D9E) LDX #10 INT2BSIC LDA IMGINTV-1,X STA CHAINTRY-1,X DEX BNE INT2BSIC (9DA9) JMP BYPASWRM ------------ * Copy image of APPLESOFT's entry point vector * table to the active entry point vector table. (9DAC) ISFPROM LDA #$40 ;Set active basic flag to #$40 to STA ACTBSFLG ;signal using Applesoft ROM. LDX #12 AROM2BSC LDA IMGFPV-1,X STA CHAINTRY-1,X DEX BNE AROM2BSC BYPASWRM SEC ;(c) = 1, signal for coldstart. (9DBC) ;(c) = 0, signal for warmstart. (9DBD) BCS CMWRMCLD ;Force branch to bypass part of the ;warmstart routine. (9DD1) CMWRMCLD PHP ;Save (c) denoting if warm or cold starting. 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 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 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 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 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 that we ;can "NOP" out this instruction to defeat ;"NOMONCIO" when cold- or warmstarting. (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 =$80 for coldstart. (9DE2) BMI LANGCOLD ;Branch if doing coldstart. (9DE7) LANGCOLD JMP (TOCLDVEC) ;Jumps to BASIC's coldstart routine ------------ ;(BASICCLD) at $E000. * NOTE: YOU ARE LEAVING THE COMFORTABLE WORLD * OF DOS AND ENTERING THE MURKY REALM OF BASIC. (E000) BASICCLD JMP BSCOLDST ;Go to basic's main coldstart. ------------ * Basic's MAIN coldstart routine. (F128) BSCOLDST LDX #$FF ;Set hi byte of current line # to $FF to STX CURLIN+1 ;signal immediate (direct) mode. LDX #$FB ;RESET STACK POINTER to point to $1FB so (F12E) TXS ;enough space is left on stack for the first ;set of link pointers & line number associated ;with an Applesoft program line. * Set GOWARM & GOSTROUT jump vectors to point to * coldstart, so no matter what happens, we will * always come back to do a coldstart. (Later, once * the coldstart is completed, the jump vectors will * be changed.) (F12F) LDA #BSCOLDST STA GOWARM+1 ; GOWARM: JMP BSCOLDST STA GOWARM+2 STA GOSTROUT+1 ; GOSTROUT: JMP BSCOLDST STY GOSTROUT+2 (F13B) JSR NORMAL ;Simulate a "NORMAL" statement. * Set the normal mode. * (INVFLG: #$FF and FLSHMSK: #$00 for normal mode.) (F273) NORMAL LDA #$FF BNE NORMINV ;ALWAYS. INVERSE LDA #$3F NORMINV LDX #0 SETINV STA INVFLG STX FLSHMSK (F27F) RTS * Put a "JMP" opcode in GOWARM, GOSTROUT, * JMPADRS & USR jump vectors. (F13E) LDA #$4C ;Opcode for "JMP" instruction. STA GOWARM STA GOSTROUT STA JMPADRS (F146) STA USR * Finish setting up the USR jump vector. (F148) LDA #IQERR STA USR+1 (F14E) STY USR+2 * Copy the image of the CHRGET routine and * the random number seed into page zero. * (NOTE: There is a bug in this routine * because it doesn't copy all of the random * number seed. One byte is left behind!) (F150) LDX #$1C ;BUG - should be #$1D. MV2ZPG LDA CHRGETFP-1,X ;Get byte of orignal and copy it to STA CHRGET-1,X ;to its zero page location. STX SPEEDFLG ;On the last pass, set speed to 255 (SPEEDFLG=1). DEX (F15A) BNE MV2ZPG * Set up more zero-page locations. (F15C) STX TRCFLG ;Simulate a "NOTRACE" statement. TXA STA TEMPRY ;Contains a #$00 expect during INIT routine. STA LASTPT+1 ;Always equals $00. PHA ;Put a $00 on the stack at $1FB (not used). LDA #3 ;Set the length for the temporary string STA DSCLEN ;descriptor for use by garbage subroutines. (F168) JSR CRDO ;Go print a . (DAFB) CRDO LDA #$0D ;Positive ASCII for . (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 output handling routine. (DB64) (FDED) COUT JMP (CSW) ;DOS intercepts output via CSW hook. ------------ * 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 ;$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. * Not doing warmstart, so check (a) to see * if using "?" associated with READing an * INPUT statement. (9EF8) CMP #"?" BEQ OPUTHDL6 ;Branch if doing a READ. CMP PROMPT ;Is (a) = the prompt character? BEQ SET2EVAL ;Branch if about to print a prompt. SETIGNOR LDX #2 ;Set condition 2 for default to signal STX OPUTCOND ;that non-DOS commands should be ignored. CMP DCTRLCHR ;Is the char = DOS's control character? (9F08) BNE OPUTHDL2 ;No. * Output handler 2. * (Ignore non-DOS commands.) (9F23) OPUTHDL2 CMP #$8D ;Is char a ? 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 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 & retrieve 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. (DB67) AND #$7F ;Convert char back to positive ASCII. 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 in 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 char back from stack. (DB70) RTS (DB00) EOR #$FF ;No reason for this? (DB02) RTS (F16B) . . - find the highest RAM location in the machine. - put the address (plus 1) of the highest memory location available to Applesoft in MEMSIZ ($73). - set end of free space/top of string storage (FRETOP, $6F). - turn off the $D6 run protection switch. - put a $00 in $800. - make sure that there is at least 1 page of free space between the start of the Applesoft program (TXTTAB, $67) and the end of free space (FRETOP, $6F). - simulate a NEW (& CLEAR) command. (Adjusts almost all major zero page pointers.) - set USR vector jump ($0A - $0C). - set GOWARM vector jump ($00 - $02). . . . (F1D2) JMP (GOWARM+1) ;Jump to basic's main command loop ------------ ;(ie. warmstart routine) called RESTART. * BASIC'S WARMSTART ROUTINE. * Enter with OPUTCOND = 0 and CONDNFLG = $80 * for coldstart or $00 for warmstart. (D43C) RESTART JSR CRDO * Print a through basic, DOS's * output handler (OPUTINCP) & the monior. (DAFB) CRDO . . (See dis'mbly above.) . . (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 $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. (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. * Not doing warmstart, so check (a) to see * if using "?" associated with READing an * INPUT statement. (9EF8) CMP #"?" (9EFA) BEQ OPUTHDL6 ;Branch if getting ready ;to read a text file byte. (9EFC) CMP PROMPT ;Are we printing a prompt? (9EFE) BEQ SET2EVAL ;Branch if about to print prompt. (9F27) SET2EVAL LDX #0 ;SET CONDITION0 - evaluate start of line. STX OPUTCOND (9F2C) JMP DSPLYALL ;Go display char. ------------ * 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.) . . (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. (9E81) INPTINCP JSR PREP4DOS ;Save regs & stk ptr * Adjust & save stk * ptr so can later * rtn to $FD38. * Pt hks at true * I/O handlers. (9ED1) PREP4DOS . . (See dis'mbly above.) . . (RTS) (9E84) LDA CONDNFLG ;Test if doing (9E87) BEQ INPUTWRM ;warmstart. ;Fall thru if ;reading. (9E89) PHA ;Save condition flag. LDA ASAVED ;Put substitute STA (BASL),Y ;cursor back on scrn PLA ;Get condition val. (9E90) BMI INPUTCLD ;Branch 4 coldstart. * Doing a coldstart. (9E95) INPUTCLD JSR KEYCOLD * Initial processing * when 1rst keyboard * input request is * made by basic after * a coldstart entry. (9DEA) KEYCOLD . . ............................................. . * Test if using A(RAM) or not. . * On entry, (a) = contents of CONDNFLG. . * = $00 = warmstart. . * = $01 = reading. . * = $80 = coldstart. . * = $C0 = using A(RAM). . (9DEA) . KEYCOLD ASL ;(a) * 2 to drop out hi bit. . (9DEB) BPL SKPDARAM ;Branch if not using A(RAM). . . * Using A(RAM) which was loaded via . * Integer basic (ROM). . (9DED) STA ACTBSFLG ;Using A(RAM), set active . ;basic flag to #$80. . . * Copy image of A(RAM)'s entry pt vector . * tbl to the active entry pt vector tbl. . (9DF0) LDX #12 . ARAM2BSC LDA IMGARAMV-1,X . STA CHAINTRY-1,X . DEX . (9DF9) BNE ARAM2BSC . . * Blank out the primary file name buffer . * to make sure a "HELLO" file won't be run. . (9DFB) LDX #29 ;30 bytes to copy (0 - 29) . BLNKPRIM LDA SCNDFNBF,X ;Copy blank secondary . STA PRIMFNBF,X ;to primary. . DEX . (9E04) BPL BLNKPRIM . . * Build DOS buffers and set condition. . (9E06) . SKPDARAM LDA MAXDFLT ;Set MXFILVAL to a default . ;value of 3. . (9E09) STA MXFILVAL ;Note: Default value can be . ;changed by setting MAXFDFLT . ;between 1 and 16 & then . ;INITing a disk. . (9E0C) JSR BILDBUFS ;Go build the DOS buffers. . . (A7D4) . BILDBUFS . . . . (Long routine, see dis'mbly . given in the MAXFILES cmd.) . . . . . (RTS) . . (9E0F) LDA EXECFLAG ;Chk if exec file actv. . (9E12) BEQ SKPDEXEC ;Branch if not EXECing. . . (9E1D) . SKPDEXEC JSR RESTAT0 . . * Reset CONDNFLG & OPUTCOND . * = 0 to signal file not . * being read & set . * condition to evaluate . * start of line when we . * return to OPUTINCP. . (A75B) . RESTAT0 LDY #0 . STY CONDNFLG . STY OPUTCOND . (A763) RTS . . * Check if the disk was just booted. . * (If just booted disk, NDX2CMD contains a $00 . * which was etched on the disk when the disk . * was originally booted.) . (9E20) LDA NDX2CMD ;Was last command an "INIT"? . (9E23) BNE OLDBOOT ;No. . . * Disk was just booted, so copy . * the IMAGE of DOS's entry point . * vector table to page 3. . (9E25) LDX #47 . STOR3DOS LDA IMGDOSVT,X . STA PG3DOSVT,X . DEX . (9E2E) BPL STOR3DOS . . * Program the reset key to point at . * DOS's warmstart routine. . * . * Note that the reset key can be . * programmed to point at any location . * simply by putting the address of the . * target routine (in low/hi format) in . * #3F2/$3F3. Next, EOR the contents of . * $3F3 with the number #$A5 and put the . * result in $3F4. (If $3F3 EOR #$A5 . * is not equal to $3F4, then the disk . * reboots and a coldstart is done.) . (9E30) LDA IMGDOSVT+2 . STA RESETVEC+1 . EOR #$A5 . STA VLDBYTE . LDA IMGDOSVT+1 . (9E3E) STA RESETVEC . . * Set the command index to RUN . * the "HELLO" file. . (9E41) LDA #6 ;Command index for RUN. . ;(Can be changed to BRUN, . ;etc.) . (9E43) BNE DOPENDNG ;ALWAYS. . . * Go do the pending command. If the . * disk was just booted, then RUN the . * "HELLO" file. Note: The actual name . * of the HELLO file resides in the primary . * filename buffer. It was written to the . * disk as part of the DOS image when the . * disk was INITed. Therefore, if you want . * to change the name of the HELLO file, . * you must: . * 1) change the file name in the . * file name field section of . * the appropriate directory . * sector. (Easiest to use . * the RENAME command.) . * 2) zap the primary file name . * buf on the disk (trk$01, . * sec $09$, offsets $75 to $92. . (9E4A) . DOPENDNG STA NDX2CMD ;Set cmd index & go do cmd. . (9E4D) JMP DODOSCMD . ------------ . . * Do the DOS command. . (A180) . DODOSCMD JSR RESTAT0 ;Reset condition 0. . . * Reset CONDNFLG & OPUTCOND . * to 0 so signal file not . * being read & set . * condition to evaluate . * start of line when we . * return to OPUTINCP. . (A75B) . RESTAT0 LDY #0 . STY CONDNFLG . STY OPUTCOND . (A763) RTS . . (A183) JSR CLRFMPRM . . * Zero out the fm parm list. . (A1AE) . CLRFMPRM LDA #0 . LDY #$16 . ZFMPARM STA FMPRMLST-1,Y . DEY . BNE ZFMPARM . (A1B8) RTS . . * Use the command index to get the . * address (minus 1) of the command's . * entry point. Stick the entry point . * address on the stack (hi byte first) . * & then do a funny jump to execute . * the command. . (A186) LDA NDX2CMD ;(a) = index to command. . (A189) TAX ;(x) = index to table of . ;entry points. . (A18A) LDA CMDTBL+1,X ;Get addr of the cmd's . (A18D) PHA ;routine & put it on the . ;stack (hi byte first). . (A18E) LDA CMDTBL,X . PHA . (A192) RTS ;Do a stack jump to process . ;the command. . . . . . . (EXECUTE THE COMMAND, IE. RUN THE . HELLO FILE WHEN COLDSTARTING. . . . . . NOTE: PARTS OF THE FOLLOWING DIS'MBLY ARE . VERY FRAGMENTED. IT IS ONLY MEANT . TO ILLUSTRATE THE PATTERN OF PROGRAM . FLOW. SEE DIS'MBLY OF RUN & LOAD . COMMANDS FOR MORE DETAIL. . . * Run command handler. . (A4D1) . CMDRUN LDA ACTBSFLG ;Check which basic is . ;current. . ;Contains $40 if A(ROM), . ;$80 if A(RAM), $00 if Int. . (A4D4) BEQ LOAD4RUN ;Branch if using Integer. . (A4D6) STA RUNTRUPT ;SET THE RUN INTERCEPT FLAG . ;TO DENOTE THAT A RUN CMD IS . ;BEING INTERRUPTED TO . ;ACCOMODATE A LOAD. . LOAD4RUN JSR CMDLOAD . . (A413) . CMDLOAD . . . . (Load the HELLO file.) . . . . . - point I/O hooks at DOS. . . . . . (A44D) JMP (RLOCNTRY) . ------------ . . (D4F2) . SETLINKS . . . . - Set up ZERO PAGE POINTERS. . - Adjust link pointers in . the HELLO program (so it . is relocatable). ............................................. . . . . ............<<< S T A C K P O I N T E R W A S R E S E T >>>................................................. . . . . (D43C) RESTART JSR CRDO (DAFB) CRDO LDA #$0D ;Positive ASCII for . (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 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 wo when we INX ;later restore it & (9EDD) STX STKSAVED ;then hit an "RTS" ;we will 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? BEQ NONTRUPT ;Branch if not. (9EF0) JMP FINSHRUN ;Finish off the RUN command. ------------ * Finish off the RUN command because * it was interrupted to do a LOAD. (9F78) FINSHRUN LDA #0 ;Zero out the run intercept flag. STA RUNTRUPT (9F7D) JSR INITIOHK ;Reset I/O hooks to pt at DOS. * Initialize the I/O hooks so that DOS * intercepts all input & output. (A851) INITIOHK . . (See dis'mbly given above.) . . (RTS) (9F80) JMP RUNFPINT ;Jump back into the RUN command ------------ ;to finish it off. ;NOTE: The stack was reset so ;we return to the correct level. (A4DC) RUNFPINT JSR CRVIADOS (9FC8) CRVIADOS LDA #$8D ;. (9FCA) JMP GODSPLY ;Go print the . ------------ (9FC5) GODSPLY JMP (CSW) ;AT THIS POINT IN ------------ ;TIME, DOS INTERCEPTS ;THE OUTPUT. * DOS's output intercept routine. (9EBD) OPUTINCP JSR PREP4DOS * Save registers. * Restore the true * I/O hooks. * Adjust & save the * stk ptr so can * later rtn to $A4DF (9ED1) PREP4DOS STA ASAVED STX XSAVED STY YSAVED TSX INX INX STX STKSAVED UNCONDOS LDX #3 SETRUHKS LDA CSWTRUE,X STA CSW,X DEX BPL SETRUHKS (9EEA) RTS * Use current OPUTCOND value to * index table containing the * address of output condition * handlers. Do a "stack jump" * to the appropriate condition * handler entry point. (9EC0) LDA OPUTCOND (9EC3) ASL ;Times 2 cause 2 ;bytes/address. (9EC4) TAX ;Set (x) to index ;tbl of entry pt ;addrs. (9EC5) LDA OUTHNDTB+1,X ;Put adr of PHA ;output handler on LDA OUTHNDTB,X ;stk (hi byte 1rst) (9ECC) PHA ;& do a "stack jump" ;to the appropriate ;entry point. (9ECD) 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. * RUN not interrupted. (9EF3) NONTRUPT LDX CONDNFLG ;Get condition. (9EF6) BEQ SETIGNOR ;Branch for warm. (9F00) SETIGNOR LDX #2 ;SET CONDITION 2. (9F02) STX OPUTCOND ;Signal ignore ;non-DOS cmds. (9F05) CMP DCTRLCHR ;DOS's ctrl char? (9F08) BNE OPUTHDL2 ;No. * Output handler 2. * (Ignore non-DOS cmds.) (9F23) OPUTHDL2 CMP #$8D ;? BNE DSPLYALL ;No. SET2EVAL LDX #0 ;SET CONDITION 0 STX OPUTCOND ;(evaluate start (9F2C) JMP DSPLYALL ;of line). ------------ * Display the char. (9FA4) DSPLYALL JSR RESTOREG * Restore registers. (9FBA) RESTOREG LDA ASAVED LDY YSAVED LDX XSAVED SEC (9FC4) RTS (9FA7) JSR GODSPLY (9FC5) GODSPLY JMP (CSW) ------- * PRINT A THRU * TRUE OUTPUT HANDLER. (FDF0) COUT1 . . (See dis'mbly in APPLE II REFERENCE MANUAL.) . . (RTS) * Save registers & reset hooks. (9FAA) STA ASAVED STY YSAVED (9FB0) STX XSAVED * 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. (A4DF) JSR INITIOHK * Initialize I/O hks * so DOS intercepts * all input & output. (A851) INITIOHK . . (See dis'mbly above.) . . (RTS) (A4E2) JMP (RUNTRY) ;Go execute the prgm. ------------ ;(RUNTRY points to RUNFPROM if using ;A(ROM) or FPRAMRUN if using A(RAM)). (A4FC) RUNFPROM JSR SETZPTRS (D665) SETZPTRS . . - simulate CLEAR & RESTORE statements - reset important zero page pointers - REINTIALIZE THE STACK POINTER TO POINT TO $1F8 (while retaining return address). . . (D696) RTS . . ............. <<< S T A C K P O I N T E R W A S R E S E T >>>......................... . . (A4FF) STA PROMPT ;Zero out the prompt & on-err flag. STA ERRFLG (A503) JMP NEWSTT ;Jump into BASIC to execute the program. ------------ (D7D2) NEWSTT . . - EXECUTES THE APPLESOFT PROGRAM. . . - pops in & out of DOS whenever a line containing a PRINT, INPUT or GET is encountered. . . BEQ RESTART Once again the RESTART ($D43C) routine is entered. However this time execution flows through DOS's output (OPUTINCP, $9EBD) and input (INPTINCP, $9E81) handlers in a manner different than that depicted above. Because the flags are set as shown below, the computer eventually ends up requesting the operator to input commands via the KEYBOARD: CONDNFLG: $00, ACTBSFLG: $40, RUNTRUPT: $00, and OPUTCOND: $00. The exact execution pattern is shown in the disassembly of the RESTART routine described in the file titled "DOSWARMSTART".