; ============================================================================== ; Apple II [$D0 ROM] (341-0016) - Programmer's Aid #1 [1978] ; ------------------------------------------------------------------------------ ; Part 2 [$D400~$D4D4]: Apple II BASIC Renumber / Append Subroutines ; Version Two by Steve Wozniak [WOZ], 1978-04-12; ; Copyright (c) 1978 by Apple Computer Inc. All Rights Reserved ; ------------------------------------------------------------------------------ ; Instructions are in the Programmer's Aid #1 Installation and Operating Manual ; ============================================================================== ; Analyzed (via McFadden's SourceGen) by James Davis [Last Updated: 2020/06/10] ; ============================================================================== ; ; **************************************** ; * * ; * RENUMBER * ; * >CLR * ; * >START= * ; * >STEP= * ; * >CALL -10531 * ; * =($D6DD) * ; * * ; * OPTIONAL * ; * >FROM= * ; * >TO= * ; * >CALL -10521 * ; * =($D6E7) * ; * * ; * USE RENX ENTRY * ; * FOR RENUMBER ALL * ; * * ; **************************************** ; ; These Entry Points (in box above), -10531 = $D6DD & -10521 = $D6E7, are ; located elsewhere, in another section of binary code. I'll need to get ; "A Round Tuit" (at a later date), if you want to see it (done/analyzed). ; Done, See: Apple II Programmers Aid 1.2.5.$D692~$D716 - Entry Points. ; ; ============================================================================== ; Renumber/Append 6502 Equates: ; ============================================================================== R0L EQU $00 {addr/1} ;Sweet 16 Register #0, Low R0H EQU $01 {addr/1} ;Sweet 16 Register #0, High R11L EQU $16 {addr/1} ;Sweet 16 Register #11, Low R11H EQU $17 {addr/1} ;Sweet 16 Register #11, High MEMFULL EQU $E36B ;Integer BASIC: Mem Full Error PRDEC EQU $E51B ;Integer BASIC: Print Decimal Number RANGERR EQU $EE68 ;Integer BASIC: Range Error LOAD EQU $F0DF ;Integer BASIC: Load from Tape Subroutine SW16 EQU $F689 ;Sweet 16 Interpreter (Op-Codes follow it) CROUT EQU $FD8E ;Monitor: Print Carriage Return Subroutine COUT EQU $FDED ;Monitor: Character Output Subroutine ORG $D400 ; ; ============================================================================== ; *** SourceGen needs a way to interpret Sweet 16 Operations like the following: ; [See: "SWEET16: The 6502 Dream Machine"; BYTE Magazine, Nov 1977, Pgs 150~159] ; [And: "Apple II Reference Manual (Red Book)"; §C6 Sweet 16 Listing, Pgs 96~99] ; ============================================================================== ; ; ; ============================================================================== ; Renumber/Append 6502 Equates: ; ============================================================================== ; A2 Locations used here (within SW16 Code Blocks, but not listed/decoded above) ; ------------------------------------------------------------------------------ ; HIMEM EQU $4C {addr/2} ;Integer BASIC: HIMEM Pointer, Low/High ; PPL EQU $CA {addr/2} ;Integer BASIC: Program Pointer, Low/High ; PVL EQU $CC {addr/2} ;Integer BASIC: Variable Pointer, Low/High ; ============================================================================== ; ; ; ============================================================================== ; General Sweet 16 Equates: Zero-Page Registers used for SW16 Interpreter Op's ; ============================================================================== ; R0 EQU $00 {addr/2} ;Sweet 16 Register #0 == SW16 Accumulator ; R0L EQU $00 {addr/1} ;Sweet 16 Register #0, Low ; R0H EQU $01 {addr/1} ;Sweet 16 Register #0, High ; ------------------------------------------------------------------------------ ; R1 EQU $02 {addr/2} ;Sweet 16 Register #1 ; R1L EQU $02 {addr/1} ;Sweet 16 Register #1, Low ; R1H EQU $03 {addr/1} ;Sweet 16 Register #1, High ; ------------------------------------------------------------------------------ ; R2 EQU $04 {addr/2} ;Sweet 16 Register #2 ; R2L EQU $04 {addr/1} ;Sweet 16 Register #2, Low ; R2H EQU $05 {addr/1} ;Sweet 16 Register #2, High ; ------------------------------------------------------------------------------ ; R3 EQU $06 {addr/2} ;Sweet 16 Register #3 ; R3L EQU $06 {addr/1} ;Sweet 16 Register #3, Low ; R3H EQU $07 {addr/1} ;Sweet 16 Register #3, High ; ------------------------------------------------------------------------------ ; R4 EQU $08 {addr/2} ;Sweet 16 Register #4 ; R4L EQU $08 {addr/1} ;Sweet 16 Register #4, Low ; R4H EQU $09 {addr/1} ;Sweet 16 Register #4, High ; ------------------------------------------------------------------------------ ; R5 EQU $0A {addr/2} ;Sweet 16 Register #5 ; R5L EQU $0A {addr/1} ;Sweet 16 Register #5, Low ; R5H EQU $0B {addr/1} ;Sweet 16 Register #5, High ; ------------------------------------------------------------------------------ ; R6 EQU $0C {addr/2} ;Sweet 16 Register #6 ; R6L EQU $0C {addr/1} ;Sweet 16 Register #6, Low ; R6H EQU $0D {addr/1} ;Sweet 16 Register #6, High ; ------------------------------------------------------------------------------ ; R7 EQU $0E {addr/2} ;Sweet 16 Register #7 ; R7L EQU $0E {addr/1} ;Sweet 16 Register #7, Low ; R7H EQU $0F {addr/1} ;Sweet 16 Register #7, High ; ------------------------------------------------------------------------------ ; R8 EQU $10 {addr/2} ;Sweet 16 Register #8 ; R8L EQU $10 {addr/1} ;Sweet 16 Register #8, Low ; R8H EQU $11 {addr/1} ;Sweet 16 Register #8, High ; ------------------------------------------------------------------------------ ; R9 EQU $12 {addr/2} ;Sweet 16 Register #9 ; R9L EQU $12 {addr/1} ;Sweet 16 Register #9, Low ; R9H EQU $13 {addr/1} ;Sweet 16 Register #9, High ; ------------------------------------------------------------------------------ ; R10 EQU $14 {addr/2} ;Sweet 16 Register #10 ; R10L EQU $14 {addr/1} ;Sweet 16 Register #10, Low ; R10H EQU $15 {addr/1} ;Sweet 16 Register #10, High ; ------------------------------------------------------------------------------ ; R11 EQU $16 {addr/2} ;Sweet 16 Register #11 ; R11L EQU $16 {addr/1} ;Sweet 16 Register #11, Low ; R11H EQU $17 {addr/1} ;Sweet 16 Register #11, High ; ------------------------------------------------------------------------------ ; R12 EQU $18 {addr/2} ;Sweet 16 Register #12 ; R12L EQU $18 {addr/1} ;Sweet 16 Register #12, Low ; R12H EQU $19 {addr/1} ;Sweet 16 Register #12, High ; ------------------------------------------------------------------------------ ; R13 EQU $1A {addr/2} ;Sweet 16 Register #13 ; R13L EQU $1A {addr/1} ;Sweet 16 Register #13, Low ; R13H EQU $1B {addr/1} ;Sweet 16 Register #13, High ; ------------------------------------------------------------------------------ ; R14 EQU $1C {addr/2} ;Sweet 16 Register #14 ; R14L EQU $1C {addr/1} ;Sweet 16 Register #14, Low ; R14H EQU $1D {addr/1} ;Sweet 16 Register #14, High ; ------------------------------------------------------------------------------ ; R15 EQU $1E {addr/2} ;Sweet 16 Register #15 ; R15L EQU $1E {addr/1} ;Sweet 16 Register #15, Low ; R15H EQU $1F {addr/1} ;Sweet 16 Register #15, High ; ============================================================================== ; ; ; ============================================================================== ; Renumber/Append Sweet 16 Equates: SW16 Registers & Locations used here ; ============================================================================== ; ACC EQU $00 {addr/2} ;R0: Sweet 16 Accumulator ; NEWLOW EQU $01 {addr/1} ;R0H: New Initial Line Number (LNO) ; NEWINCR EQU $02 {addr/1} ;R1L: New LNO Increment (INCR) Value ; LNLO EQU $03 {addr/1} ;R1H: Low LNO of RENUM Range ; LNHI EQU $04 {addr/1} ;R2L: High LNO of RENUM Range ; TBLSTRT EQU $05 {addr/1} ;R2H: LNO Table Start ; TBLINDX1 EQU $06 {addr/1} ;R3L: Pass 1 LNO Table Index ; TBLND EQU $06 {addr/1} ;R3L: Pass 2 LNO Table End ; TBLIM EQU $07 {addr/1} ;R3H: LNO Table Limit ; PRGNDX2 EQU $07 {addr/1} ;R3H: Pass 2 Program Index ; SCR8 EQU $08 {addr/1} ;R4L: Scratch Register ; HMEM EQU $08 {addr/1} ;R4L: HIMEM (End of Program) ; SCR9 EQU $09 {addr/1} ;R4H: Scratch Register ; PRGNDX EQU $09 {addr/1} ;R4H: Pass 1 Program Index ; CHR9 EQU $09 {addr/1} ;R4H: ASCII "0" (Constant Safe) ; PRGNDX1 EQU $0A {addr/1} ;R5L: Pass 1 Program Index 1 ; CHRA EQU $0A {addr/1} ;R5L: ASCII "@" (Constant Safe) ; NEWLN EQU $0B {addr/1} ;R5H: Next "New LNO" Assignment ; TBLNDX2 EQU $0B {addr/1} ;R5H: LNO Table Index for Update ; STRCON EQU $0B {addr/1} ;R5H: BASIC String Constant Token ; NEWLN1 EQU $0C {addr/1} ;R6L: Prior "New LNO" Assignment ; MODE EQU $0C {addr/1} ;R6L: LNO Mode Constant ; REM EQU $0C {addr/1} ;R6L: BASIC REM Token ; SCRC EQU $0C {addr/1} ;R6L: Scratch Register for Append ; OLDLN EQU $0D {addr/1} ;R6H: Old LNO for Update ; CPRREG EQU $0D {addr/1} ;R6H: Compare (CPR) Register [Not R13 !!!] ; THEN EQU $0D {addr/1} ;R6H: BASIC THEN Token ; LIST EQU $0D {addr/1} ;R6H: BASIC LIST Token ; DEL EQU $0D {addr/1} ;R6H: BASIC DEL Token ; ============================================================================== ; ; ; ============================================================================== ; Apple II BASIC Renumber Subroutine - Pass 1 ; ============================================================================== ; ; ------------------------------------------------------------------------------ ; ;Optional Range Entry; Use to Renumber All D400: 20 89 F6 RENX JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)... ; ------------------------------------------------------------------------------ D403: B0 DFB $B0 ;SUB ACC ;R0: D404: 33 DFB $33 ;ST LNLO ;Set LNLO=0 D405: 34 DFB $34 ;ST LNHI ;Set LNHI=0 D406: F4 DFB $F4 ;DCR LNHI ;Reduce LNHI (from 0 to -1) D407: 00 DFB $00 ;RTN ;[Return to 6502 Mode] ; ============================================================================== ; Apple II BASIC Renumber Subroutine ; ============================================================================== ; ; ------------------------------------------------------------------------------ ; ;Both BASIC Entry Pt. Calls will Jump Here D408: 20 89 F6 RENUM JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)... ; ------------------------------------------------------------------------------ D40B: 18 4C 00 HEX 184C00 ;SET HMEM,HIMEM D40E: 68 DFB $68 ;LDD @HMEM D40F: 38 DFB $38 ;ST HMEM D410: 19 CE 00 RNUM3 HEX 19CE00 ;SET SCR9,PVL+2 D413: C9 DFB $C9 ;POPD @SCR9 ;BASIC Var Pnt to ... D414: 35 DFB $35 ;ST TBLSTRT ;<- TBLSTRT & ... D415: 36 DFB $36 ;ST TBLNDX1 ;<- TBLNDX1 D416: 21 DFB $21 ;LD NEWLOW ;Copy NEWLOW (Intl) to ... D417: 3B DFB $3B ;ST NEWLN ;<- NEWLN & ... D418: 3C DFB $3C ;ST NEWLN1 ;<- NEWLN1 D419: C9 DFB $C9 ;POPD @SCR9 ;BASIC Program Pntr to ... D41A: 37 DFB $37 ;ST TBLIM ;<- TBLIM & ... D41B: 39 DFB $39 ;ST PRGNDX ;<- PRGNDX D41C: 29 PASS1 DFB $29 ;LD PRGNDX D41D: D8 DFB $D8 ;CPR HMEM ;If PRGNDX >= HMEM, ... D41E: 03 46 DDB $0346 ;BC PASS2 ;Then Done with Pass 1 D420: 3A DFB $3A ;ST PRGNDX1 D421: 26 DFB $26 ;LD TBLNDX1 D422: E0 DFB $E0 ;INR ACC ;If < 2 Bytes avail in ... D423: D7 DFB $D7 ;CPR TBLIM ;LNO Table, then Return ... D424: 03 38 DDB $0338 ;BC MERR ;with "MEM FULL" Message D426: 4A DFB $4A ;LD @PRGNDX1 D427: A9 DFB $A9 ;ADD PRGNDX ;Add Length to Prog Index D428: 39 DFB $39 ;ST PRGNDX D429: 6A DFB $6A ;LDD @PRGNDX1 ;Line Number D42A: D3 DFB $D3 ;CPR LNLO ;If < LNLO, Goto P1C D42B: 02 2A DDB $022A ;BNC P1B D42D: D4 DFB $D4 ;CPR LNHI ;If > LNHI, Goto P1C D42E: 02 02 DDB $0202 ;BNC P1A D430: 07 30 DDB $0730 ;BNZ P1C D432: 76 P1A DFB $76 ;STD @TBLNDX1 ;Add to LNO Table D433: 00 DFB $00 ;RTN ;[Return to 6502 Mode] ; ----------------------------------- ;Print 'Old Line #' "->" 'New Line #' ; ; [SW16: (R0,R11)] in Decimal: ; ; ------------------------ ;**** 6502 Code Block Start **** D434: A5 01 LDA R0H ;Get Sweet 16 Register #0, High D436: A6 00 LDX R0L ;Get Sweet 16 Register #0, Low D438: 20 1B E5 JSR PRDEC ;Print Decimal Number D43B: A9 AD LDA #'-' | $80 ;Get a Dash Character D43D: 20 ED FD JSR COUT ;Print A-Reg to Output Device D440: A9 BE LDA #'>' | $80 ;Get a Greater Than Sign D442: 20 ED FD JSR COUT ;Print A-Reg to Output Device D445: A5 17 LDA R11H ;Get Sweet 16 Register #11, High D447: A6 16 LDX R11L ;Get Sweet 16 Register #11, Low D449: 20 1B E5 JSR PRDEC ;Print Decimal Number D44C: 20 8E FD JSR CROUT ;Print a Carriage Return ; ------------------------ ;**** 6502 Code Block End **** ; ; ------------------------------------------------------------------------------ D44F: 20 8C F6 JSR SW16+3 ;Sweet 16 Interpreter (Op-Codes follow)... ; ------------------------------------------------------------------------------ D452: 2B DFB $2B ;LD NEWLN D453: 3C DFB $3C ;ST NEWLN1 ;Copy NEWLN to NEWLN1 & ... D454: A2 DFB $A2 ;ADD NEWINCR ;Increase NEWLN by NEWINCR D455: 3B DFB $3B ;ST NEWLN D456: 0D DFB $0D ;HEX 0D ;'NUL' (Will Skip Next Op) D457: D1 P1B DFB $D1 ;CPR NEWLOW ;If Low LNO < New Low, ... ; ; ; ; ;then "RANGE ERR" D458: 02 C2 DDB $02C2 ;BNC PASS1 ;Loop if Not ; ----------------------------------- ;------------- ;Else, Print Err Message: D45A: 00 RERR DFB $00 ;RTN ;[Return to 6502 Mode] D45B: 4C 68 EE JMP RANGERR ;6502 Code: BASIC Range Error ; ----------------------------------- ;------------- ;Print Err Message: D45E: 00 MERR DFB $00 ;RTN ;[Return to 6502 Mode] D45F: 4C 6B E3 JMP MEMFULL ;6502 Code: BASIC Memory Full Error ; ----------------------------------- ;------------- ;[Continue SW16 Process]: D462: EC P1C DFB $EC ;INR NEWLN1 ;If Hi LNO <= Current NEWLN D463: DC DFB $DC ;CPR NEWLN1 ;then "RANGE ERR" ... D464: 02 F4 DDB $02F4 ;BNC RERR ;Go Print Err Message ; ; ============================================================================== ; Apple II BASIC Renumber / Append Subroutine - Pass 2 ; ============================================================================== ; D466: 19 B0 00 PASS2 HEX 19B000 ;CHR9,$00B0 ;SET (Constant)=(ASCII "0") D469: 1A C0 00 HEX 1AC000 ;CHRA,$00C0 ;SET (Constant)=(ASCII "@") ; ------------------------------------------------------------------------------ ; *** NOTE: $C0 is an "@" (AT sign)!--Not an "A" character (as shown in the ; listing in the "Programmer's Aid #1 Installation & Operating Manual")! ; ------------------------------------------------------------------------------ D46C: 27 P2A DFB $27 ;LD PRGNDX2 D46D: D8 DFB $D8 ;CPR HMEM ;If PRGNDX2 = HIMEM, ... D46E: 03 63 DDB $0363 ;BC DONE ;then Pass 2 is Done D470: E7 DFB $E7 ;INR PRGNDX2 ;Skip Length Byte D471: 67 DFB $67 ;LDD @PRGNDX2 ;Line Number D472: 3D UPDATE DFB $3D ;ST OLDLN ;Save Old LNO D473: 25 DFB $25 ;LD TBLSTRT D474: 3B DFB $3B ;ST TBLNDX2 ;Init LNO Table Index D475: 21 DFB $21 ;LD NEWLOW ;Init NEWLN to NEWLOW D476: 1C DFB $1C ;HEX 1C ;(Will Skip Next Op) D477: 2C UD2 DFB $2C ;LD NEWLN1 D478: A2 DFB $A2 ;ADD NEWINCR ;Add INCR to NEWLN1 D479: 3C DFB $3C ;ST NEWLN1 D47A: 2B DFB $2B ;LD TBLNDX2 ;If LNO TBL IDX = TBLND ... D47B: B6 DFB $B6 ;SUB TBLND ;then Done Scanning LNO TBL D47C: 03 07 DDB $0307 ;BC UD3 D47E: 6B DFB $6B ;LDD @TBLNDX2 ;Next LNO from Table D47F: BD DFB $BD ;SUB OLDLN ;Loop to UD2 If Not = OLDLN D480: 07 F5 DDB $07F5 ;BNZ UD2 D482: C7 DFB $C7 ;POPD @PRGNDX2 ;Replace Old LNO with ... D483: 2C DFB $2C ;LD NEWLN1 ;Corresponding New Line D484: 77 DFB $77 ;STD @PRGNDX2 D485: 1B 28 00 UD3 HEX 1B2800 ;SET STRCON,$0028 ;STR CON Token D488: 1C DFB $1C ;HEX 1C ;(Skips Next Two Ops) D489: 67 GOTCON DFB $67 ;LDD @PRGNDX2 D48A: FC DFB $FC ;DCR MODE ;If MODE = 0 Update LNO Ref D48B: 08 E5 DDB $08E5 ;BM1 UPDATE D48D: 47 ITEM DFB $47 ;LD @PRGNDX2 ;BASIC Token D48E: D9 DFB $D9 ;CPR CHR9 D48F: 02 09 DDB $0209 ;BNC CHKTOK ;Check Token for Special D491: DA DFB $DA ;CPR CHRA ;If >= "0" & < "@" ... D492: 02 F5 DDB $02F5 ;BNC GOTCON ;Skip Const or Update D494: F7 SPKASC DFB $F7 ;DCR PRGNDX2 D495: 67 DFB $67 ;LDD @PRONDX2 ;Skip all Neg Bytes of ... D496: 05 FC DDB $05FC ;BM SKPASC ;STR CON, REM or NAME D498: F7 DFB $F7 ;DCR PRGNDX2 D499: 47 DFB $47 ;LD @PRGNDX2 D49A: DB CHKTOC DFB $DB ;CPR STRCON ;STR CON Token? D49B: 06 F7 DDB $06F7 ;BZ SKPASC ;Yes, Skip Subseguent Bytes D49D: 1C 5D 00 HEX 1C5D00 ;SET REM,$005D D4A0: DC DFB $DC ;CPR REM ;REM Token? D4A1: 06 F1 DDB $06F1 ;B2 SKPASC ;Yes, Skip Subseguent Line D4A3: 08 13 DDB $0813 ;BM1 CONTST ;GOSUB, Look for Line # D4A5: FD DFB $FD ;DCR R13 D4A6: FD DFB $FD ;DCR R13 ;(Token $5F is GOTO) D4A7: 06 0F DDB $060F ;BZ CONTST D4A9: 1D 24 00 HEX 1D2400 ;SET THEN,$0024 D4AC: DD DFB $DD ;CPR THEN D4AD: 06 09 DDB $0609 ;BZ CONTST ;'THEN' LNO, Look for LNO D4AF: F0 DFB $F0 ;DCR ACC D4B0: 06 BA DDB $06BA ;BZ P2A ;EOL (Token 01)? D4B2: 1D 74 00 HEX 1D7400 ;SET LIST,$0074 D4B5: BD DFB $BD ;SUB LIST ;Set Mode if "LIST"|"LIST," D4B6: 09 01 DDB $0901 ;BNM1 CONTS2 ;(Tokens $74, $75) D4B8: B0 CONTST DFB $B0 ;SUB ACC ;Clear Mode for LNO D4B9: 3C CONTS2 DFB $3C ;ST MODE ;Update Check D4BA: 01 D1 DDB $01D1 ;BR ITEM ; ; ============================================================================== ; Apple II BASIC Append Subroutine ; ============================================================================== ; ; ------------------------------------------------------------------------------ ; BASIC: 1st LOAD (from Tape) 2nd Integer BASIC Program with high line numbers; ; then CALL -11076 to LOAD & Append 1st Program with low line numbers ; ------------------------------------------------------------------------------ D4BC: 20 89 F6 APPEND JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)... ; ------------------------------------------------------------------------------ D4BF: 1C 4E 00 HEX 1C4E00 ;SET SCRC,HIMEM+2 D4C2: CC DFB $CC ;POPD @SCRC ;Save HIMEM D4C3: 38 DFB $38 ;ST HMEM D4C4: 19 CA 00 HEX 19CA00 ;SET SCR9,PPL D4C7: 69 DFB $69 ;LDD @SCR9 D4C8: 7C DFB $7C ;STD @SCRC ;Set HIMEM to Preserve Prog D4C9: 00 DFB $00 ;RTN ;[Return to 6502 Mode] D4CA: 20 DF F0 JSR LOAD ;6502 Code: Load from Tape ; ; ------------------------------------------------------------------------------ ; BASIC: CALL -11059 to Recover 2nd Program when Append fails w/ Mem Full Error! ; ------------------------------------------------------------------------------ D4CD: 20 89 F6 RECOVER JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)... ; ------------------------------------------------------------------------------ D4D0: CC DFB $CC ;POPD @SCRC ;Restore HIMEM to Show ... D4D1: 28 DFB $28 ;LD HMEM ;Both Programs (Old & New) D4D2: 7C DFB $7C ;STD @SCRC D4D3: 00 DONE DFB $00 ;RTN ;[Return to 6502 Mode] ; D4D4: 60 RTS ;6502 Code: Return to Caller