; ============================================================================== ; Apple II [$D0 ROM] (341-0016) - Programmer's Aid #1 [1978] ; ------------------------------------------------------------------------------ ; Part 3 [$D4D5~$D52D]: 6502 Relocation Subroutine ; by Steve Wozniak [WOZ], 1977-11-10; ; 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/07] ; ============================================================================== ; ; ============================================================================== ; Relocater Routine Equates: ; ============================================================================== ; R1L EQU $02 {addr/1} ;Sweet 16 Register #1 INST EQU $0B {addr/3} ;3-Byte Instuction Field LENGTH EQU $2F {addr/1} ;Disassembler Instruction Display Length YSAV EQU $34 {addr/1} ;Y-Reg Safe for Monitor Command Processing A1L EQU $3C {addr/1} ;Monitor General Purpose A1-Reg, Low A4L EQU $42 {addr/1} ;Monitor General Purpose A4-Reg, Low INBUFF EQU $0200 ;Apple II Input Buffer, Start of (~1 Page) SETUSRADR EQU $D5B0 ;Sets Monitor User Command (Ctrl-Y) Vector SW16 EQU $F689 ;Sweet 16 Interpreter (Op-Codes follow it) INSDS2 EQU $F88E ;Monitor Disassembler Entry Point NXTA4 EQU $FCB4 ;Subroutine to Increment Mon A4 Register ORG $D4D5 ; ; ============================================================================== ; Relocater Routines: ; ============================================================================== ; Set Monitor User Command (Ctrl-Y) Vector to Relocater Routine Location: ; ------------------------------------------------------------------------------ ; ; ----------------------------------- ;Setup Mon User Cmd (Ctrl-Y) Location: D4D5: A9 DC SETRLCYV LDA #<RELOC ;Get Relocater Routine Address, Low D4D7: A0 D4 LDY #>RELOC ;Get Relocater Routine Address, High D4D9: 4C B0 D5 JMP SETUSRADR ;Setup Mon User Cmd (Ctrl-Y) Vector ; ============================================================================== ; Monitor User Command (Ctrl-Y) Vector Setup Routine: ; ============================================================================== ; Shared by: Relocater, Tape Verify, & RAM Test Routines; ; Located further below, between the Tape Verify & RAM Test Routines: ; ------------------------------------------------------------------------------ ; ORG $D5B0 ; ----------------------------------------- ;Setup Mon User Cmd (Ctrl-Y) Vector: ; D5B0: 8D F9 03 SETUSRADR STA USRADR+1 ;Preset User Address, Low ; D5B3: 8C FA 03 STY USRADR+2 ;Preset User Address, High ; D5B6: A9 4C LDA #$4C ;Get JMP OpCode ; D5B8: 8D F8 03 STA USRADR ;Preset to JMP OpCode ; D5BB: 60 RTS ;Return to Caller ; ============================================================================== ; ; ; ============================================================================== ; 6502 Relocation Subroutine [For use via Apple II Monitor (at Star {*} Prompt)] ; ============================================================================== ; 1. Define Blocks: *A4<A1.A2 ^Y (^Y is Ctrl-Y) ; ------------------------------------------------------------------------------ ; 2. First Segment: *A4<A1.A2 ^Y (If Code) ; *A4<A1.A2M (If Move) ; ------------------------------------------------------------------------------ ; 3. Subsequent Segments: *.A2 ^Y (If Code) ; *.A2M (If Move) ; ============================================================================== ; D4DC: A4 34 RELOC LDY YSAV ;Get Monitor Command Processing Pointer D4DE: B9 00 02 LDA INBUFF,Y ;Get Monitor Command from Input Buffer D4E1: C9 AA CMP #'*' | $80 ;Assure we are at the Monitor Prompt D4E3: D0 0C BNE RELOC2 ;Branch if Not at the Monitor Prompt ; ;Else, Initialize Relocation Pointers: D4E5: E6 34 INC YSAV ;Advance Command Processing Pointer D4E7: A2 07 LDX #7 ;Prepare to Copy 8 Bytes ... D4E9: B5 3C INIT LDA A1L,X ;From: Monitor General Purpose Registers D4EB: 95 02 STA R1L,X ;To: Sweet 16 Interpreter (ZP) Registers D4ED: CA DEX ;Reduce Byte-Count Index-Pointer D4EE: 10 F9 BPL INIT ;Loop until all Bytes have been Copied D4F0: 60 RTS ;Then Return to Caller D4F1: A0 02 RELOC2 LDY #2 ;Prepare to Copy 3 Bytes ... D4F3: B1 3C GETINS LDA (A1L),Y ;From: A1 Address Pointer [(Indirect),Y] D4F5: 99 0B 00 STA INST,Y ;To: 3-Byte Instuction Field [Abs,Y] D4F8: 88 DEY ;Reduce Byte-Count Index-Pointer D4F9: 10 F8 BPL GETINS ;Loop until all Bytes have been Copied ; ;Compute Instruction Length from Op-Code: D4FB: 20 8E F8 JSR INSDS2 ;Monitor Disassembler Entry Point D4FE: A6 2F LDX LENGTH ;Disassembler Instruction Display Length ; ;^[Sets X=# of Bytes: 1, 2, or 3] D500: CA DEX ;Reduce Byte-Count Index-Pointer ; ;^[Now, # of Bytes is X+1: X= 0, 1, or 2] D501: D0 0C BNE TRANSLATE ;If Not Zero, Interpret Sweet 16 Op-Codes D503: A5 0B LDA INST ;Get Instuction from 3-Byte Field D505: 29 0D AND #%00001101 ;Weed Out Non-Zero-Page ... D507: F0 14 BEQ STINST ; 2-Byte Immediate Operations D509: 29 08 AND #%00001000 ;If Zero-Page Address, ... D50B: D0 10 BNE STINST ; Then Clear High Byte D50D: 85 0D STA INST+2 ;3-Byte Instuction Field D50F: 20 89 F6 TRANSLATE JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)... ; ============================================================================== ; *** 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] ; ============================================================================== ; Sweet 16 Equates: Zero-Page Locations used here for Sweet 16 Interpreter Op's ; ============================================================================== ; FRMBEG EQU $01 {addr/1} ;SW16/R0H: Beginning of Source Block ; FRMEND EQU $02 {addr/2} ;SW16/R1L: End of Source Block {Low/High}* ; TOBEG EQU $04 {addr/2} ;SW16/R2L: Beginning of Destination Block* ; ADR EQU $06 {addr/2} ;SW16/R3L: Address Part of Instuction ; ============================================================================== ; TRANSLATE JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)... ; ^ XLATE ^ ------------------------------------- ;If Address of Zero Page D512: 22 DFB $22 ;LD FRMEND ;or Absolute Address is in D513: D6 DFB $D6 ;CPR ADR ;Source (FRM) Block then D514: 02 06 DDB $0206 ;BNC SW16RT ;Substitute: D516: 26 DFB $26 ;LD ADR ;(Address Part of Instuction) D517: B1 DFB $B1 ;SUB FRMBEG ;-(Source Start Address) D518: 02 02 DDB $0202 ;BNC SW16RT ;[Exit: Branch if No Carry] D51A: A4 DFB $A4 ;ADD TOBEG ;+(Destination Start Address) D51B: 36 DFB $36 ;ST ADR ;(Address Part of Instuction) D51C: 00 :SW16RT DFB $00 ;RTN ;[Return to 6502 Mode] ; ============================================================================== ; D51D: A2 00 STINST LDX #0 ;Clear X-Index; Prep to Copy LENGTH Bytes D51F: B5 0B STINS2 LDA INST,X ;From: 3-Byte Instuction Field [Abs,X] D521: 91 42 STA (A4L),Y ;To: A4 Address Pointer [(Indirect),Y] D523: E8 INX ;Advance X-Index D524: 20 B4 FC JSR NXTA4 ;Subroutine to Increment Mon A4 Register D527: C6 2F DEC LENGTH ;Disassembler Instruction Display Length D529: 10 F4 BPL STINS2 ;Loop until all Bytes have been Copied D52B: 90 C4 BCC RELOC2 ;Loop until Relocation is Finished D52D: 60 RTS ;Return to Caller