;Disassembly of Opus DDOS 3.46 and variants
;Greg Cook, 10 March 2021
;Pass this file through a C preprocessor or the attached asm2bin.pl
;to produce a listing that assembles one of the six enclosed
;versions of DDOS.
;Define one of the following symbols during preprocessing to assemble
;its associated target, listed in estimated date order:-
;Symbol: _DDOS346PRE (default)
;Source: http://mdfs.net/Mirror/Image/Challenger/DISS.ZIP
;Path: DDOS346
;Compatibility: Opus DDOS interface for Model B, WD 1770
;Banner version: 3.46
;*ROMID string: 3.45 01-03-86
;Code length: &3F3F
;Acorn CRC: &3C3A
;PKZIP CRC: &C146F266
;XFER CRC: &A22A48A5
;Cksum: 2457132685
;Symbol: _DDOS316
;Source: http://regregex.bbcmicro.net/romsearch.zip
;Path: romsearch/slogger/Slogger-DDOS-3.16-Copyright-c-1984-Slogger-Software-alt1
;Compatibility: Opus DDOS interface for Model B, WD 2791
;Banner version: 3.16
;*ROMID string: 3.16 01-03-86
;Code length: &3F30
;Acorn CRC: &07FD
;PKZIP CRC: &268EBC0D
;XFER CRC: &9E06A31E
;Cksum: 2106235609
;Symbol: _DDOS336
;Source: http://regregex.bbcmicro.net/romsearch.zip
;Path: romsearch/slogger/Slogger-DDOS-3.36-Copyright-c-1984-Slogger-Software
;Compatibility: Opus DDOS interface for Model B, WD 2793
;Banner version: 3.36
;*ROMID string: 3.36 01-03-86
;Code length: &3F1E
;Acorn CRC: &7196
;PKZIP CRC: &2F400F69
;XFER CRC: &0C4CD447
;Cksum: 1809122509
;Symbol: _DDOS346
;Source: http://wouter.bbcmicro.net/bbc/bestanden/roms-2009.01.28.zip
;Path: roms/kopie_van_disk/Opus/Opus__Slogger_DDOS__3.46
;Compatibility: Opus DDOS interface for Model B, WD 1770
;Banner version: 3.46
;*ROMID string: 3.46 01-03-86
;Code length: &3F40
;Acorn CRC: &9C48
;PKZIP CRC: &BF9C35CF
;XFER CRC: &927A0EC3
;Cksum: 3431659878
;Symbol: _DDOS356
;Source: http://mdfs.net/Mirror/Image/Challenger/DISS.ZIP
;Path: DDOS356 (edited)
;Compatibility: Built-in interface on Master 128, WD 1770
;Banner version: 3.56
;*ROMID string: 3.45 01-03-86
;Code length: &3F59
;Acorn CRC: &5DEC
;PKZIP CRC: &1571DAE6
;XFER CRC: &94C83A73
;Cksum: 1522787914
;Symbol: _DDOS357
;Source: http://mdfs.net/Mirror/Image/Challenger/DISS.ZIP
;Path: DDOS357 (edited)
;Compatibility: Built-in interface on Master 128, WD 1770
;Banner version: 3.58
;*ROMID string: 3.45 01-03-86
;Code length: &3F6C (=&3F5A-&0003+&0015)
;Acorn CRC: &B59D
;PKZIP CRC: &7ED71962
;XFER CRC: &59A1B24D
;Cksum: 1255307783
;Symbols to enable RAM disc use. Maximum sizes supported:
;_DDOSRAM Model B, 256 KiB on DDOS RAM pack
;_BMEM Model B, 128 KiB paged RAM to Greg Cook's BMem recipe
;_TWOMEG Model B, 128 KiB on Solidisk Twomeg board
;_PLUGIN Model B, 128 KiB (4x RAM/ROM modules from BooBip.com)
;_PLUGIN2 Model B, 128 KiB (4x RAM/ROM modules, alternate layout)
;_MASTER Master, 128 KiB (64 KiB internal + 2x 32 KiB cartridges)
;_RAMINIT64K *RAMINIT creates 64 KiB RAM disc catalogue
;_RAMINIT256K *RAMINIT creates 256 KiB RAM disc catalogue
;Other interoperability symbols:
;_BUGFIX Fix parsing of file specifications "*" and "
.*"
; Ignore NMIs during track seek operations
;_DFSFIX Provide OSARGS 3,Y (EXT#=), OSFILE 7/9/11
; (create/stamp file) and minimal RISC OS semantics
#undef _RAMBUGFIX
#if defined _DDOSRAM
# define _RAMBUGFIX 1
#elif defined _BMEM
# define _RAMBUGFIX 1
#elif defined _TWOMEG
# define _RAMBUGFIX 1
#elif defined _PLUGIN
# define _RAMBUGFIX 1
#elif defined _PLUGIN2
# define _RAMBUGFIX 1
#elif defined _MASTER
# define _RAMBUGFIX 1
#endif
8000 EQUB &00 ;Language entry
8001 EQUB &00
8002 EQUB &00
#if defined _DDOS357
8003 4C 46 80 JMP P046 ;Service entry
#else
8003 4C 47 80 JMP P047 ;Service entry
#endif
8006 EQUB &82 ;rom type: service only
8007 EQUB &1A ;Copyright offset pointer
8008 EQUB &35 ;Version No.
#if defined _DDOS356
8009 EQUS "Master DDOS " ;title
8015 EQUB &00 ;terminator byte
8016 EQUS "3.56" ;version string
801A EQUB &00 ;terminator byte
801B EQUS "(C)Copyright (c) 1990 F.T.C." ;copyright pointer validated by MOS prior to accepting ROM
8037 EQUB &00 ;terminator byte
8038 EQUS "Software "
8041 EQUB &00 ;terminator byte
#elif defined _DDOS357
8009 EQUS "Master DDOS " ;title
8015 EQUB &00 ;terminator byte
8016 EQUS "3.57" ;version string
801A EQUB &00 ;terminator byte
801B EQUS "(C)Copyright (c) 1990 F.T.C." ;copyright pointer validated by MOS prior to accepting ROM
8037 EQUB &00 ;terminator byte
8038 EQUS "Software "
8041 EQUB &00 ;terminator byte
#else /* COMMON */
8009 EQUS "Slogger DDOS" ;title
8015 EQUB &00 ;terminator byte
8016 EQUS "3.x5" ;version string
801A EQUB &00 ;terminator byte
801B EQUS "(C)Copyright (c) 1984 Slogger Software" ;copyright pointer validated by MOS prior to accepting ROM
8041 EQUB &00 ;terminator byte
#endif /* _DDOS356 */
.P042
8042 6C 1E 02 JMP (&021E) ;Issue Filing System Call
#if defined _DDOS357
;////////////////////////////////////////////// DDOS 3.57
8045 60 RTS
.P046 ;ROM service
8046 20 A9 BA JSR SAA9
8049 C9 01 CMP #&01
804B D0 07 BNE P054
804D C0 17 CPY #&17 ;Service call &01 = reserve absolute workspace
804F B0 02 BCS P053 ;if workspace < 9 pages (+&0E = &17)
8051 A0 17 LDY #&17 ;then reserve 9 pages abs workspace.
.P053
8053 60 RTS
.P054
8054 C9 02 CMP #&02
8056 D0 18 BNE P070
8058 98 TYA ;Service call &02 = reserve private workspace
8059 85 B1 STA &B1 ;y=lowest free page, store in pointer
805B 9D F0 0D STA &0DF0,X ;and in the MOS workspace for this purpose
805E A9 00 LDA #&00 ;clear LSB of pointer
8060 85 B0 STA &B0
8062 A0 C0 LDY #&C0 ;clear offset &C0 of page
8064 91 B0 STA (&B0),Y ;b7=1 iff private page initialised
8066 C8 INY ;and offset &C1
8067 91 B0 STA (&B0),Y ;b7=1 iff we own the shared workspace
8069 A4 B1 LDY &B1 ;y = 2 + address of private page
806B C8 INY ;thus reserving two private pages
806C C8 INY
806D A9 02 LDA #&02 ;restore call number and pass to next ROM.
.P06F
806F 60 RTS
.P070
8070 C9 03 CMP #&03
8072 D0 19 BNE P08D
8074 84 B3 STY &B3 ;Service call &03 = boot
8076 20 00 A3 JSR R300 ;save boot flag in scratch space
8079 A9 7A LDA #&7A ;call OSBYTE &7A = scan keyboard from &10+
807B 20 F4 FF JSR &FFF4
807E 8A TXA ;test returned key code
807F 30 09 BMI P08A ;if N=1 no key is pressed, so init and boot
8081 C9 32 CMP #&32 ;else if key pressed is not D
8083 D0 EA BNE P06F ;then exit
8085 A9 78 LDA #&78 ;else register keypress for two-key rollover
8087 20 F4 FF JSR &FFF4
.P08A
808A 4C DB 81 JMP P1DB ;initialise DDOS and boot default volume
.P08D
808D C9 04 CMP #&04
808F D0 45 BNE P0D6
8091 20 00 A3 JSR R300 ;Service call &04 = unrecognised OSCLI
8094 BA TSX ;save stack pointer in scratch space
8095 86 B8 STX &B8
8097 98 TYA
8098 A2 5F LDX #&5F ;point XY to utility command table at &8E5F
809A A0 8E LDY #&8E
809C 20 C7 8E JSR PEC7 ;search for command in table
809F B0 4B BCS P0EC ;if not found then exit
80A1 86 AF STX &AF ;else save pointer to syntax byte in workspace
80A3 5A PHY ;save offset of command line tail on stack
80A4 AD 1E 02 LDA &021E ;test address in FSCV
80A7 C9 69 CMP #&69 ;if it does not point to MOS ROM at &FB69
80A9 D0 21 BNE P0CC ;then only execute *command if syntax b7=0
80AB AD 1F 02 LDA &021F
80AE C9 FB CMP #&FB
80B0 D0 1A BNE P0CC
80B2 20 14 A8 JSR R814 ;else FSCV not intercepted.
80B5 86 B0 STX &B0 ;call OSBYTE &A8 = get extended vector table
80B7 84 B1 STY &B1 ;address in XY. store XY as pointer
80B9 A0 2D LDY #&2D ;test sixteenth entry in table = FSCV
80BB B1 B0 LDA (&B0),Y ;if FSCV vector address is not &BFE8
80BD C9 E8 CMP #&E8
80BF D0 0B BNE P0CC ;then only execute *command if syntax b7=0
80C1 C8 INY
80C2 B1 B0 LDA (&B0),Y
80C4 C9 BF CMP #&BF
80C6 D0 04 BNE P0CC
.P0C8
80C8 7A PLY ;else restore offset of command line tail
.P0C9
80C9 6C A8 00 JMP (&00A8) ;and execute *command.
.P0CC ;*command while FSCV does not point to us
80CC A6 AF LDX &AF ;get syntax byte from command table
80CE 20 AA 00 JSR &00AA
80D1 10 F5 BPL P0C8 ;if b7=0 then execute *command
80D3 4C F2 84 JMP P4F2 ;else reset stack pointer and exit
.P0D6
80D6 C9 09 CMP #&09
80D8 D0 2E BNE P108
80DA 20 00 A3 JSR R300 ;Service call &09 = *HELP
80DD B1 F2 LDA (&F2),Y ;save AXY, test char at start of *HELP string
80DF C9 0D CMP #&0D ;if not CR then *HELP called with keyword
80E1 D0 0A BNE P0ED ;so scan keyword
80E3 A2 A7 LDX #&A7 ;else point XY to *HELP keyword table at &8EA7
80E5 A0 8E LDY #&8E
80E7 A9 04 LDA #&04 ;4 entries to print
80E9 20 F6 9F JSR QFF6 ;print *HELP keywords and pass on the call.
.P0EC
80EC 60 RTS
.P0ED
80ED 20 BB A4 JSR R4BB ;Scan *HELP keyword. call GSINIT with C=0
80F0 F0 FA BEQ P0EC ;if string is empty then pass call on
80F2 98 TYA ;else save string offset
80F3 48 PHA
80F4 A2 A7 LDX #&A7 ;point XY to *HELP keyword table at &8EA7
80F6 A0 8E LDY #&8E
80F8 20 C7 8E JSR PEC7 ;search for keyword in table
80FB B0 03 BCS P100 ;if keyword found
80FD 20 C9 80 JSR P0C9 ;then call its action address; print help
.P100
8100 7A PLY ;restore string offset
.P101
8101 20 C5 FF JSR &FFC5 ;call GSREAD
8104 90 FB BCC P101 ;until end of argument (discarding it)
8106 B0 E5 BCS P0ED ;then scan next *HELP keyword
.P108
8108 C9 12 CMP #&12 ;compare service call no. with &12 = init FS
810A 4C 4B BF JMP SF4B ;jump to patch to continue
#else /* _DDOS357 */
;////////////////////////////////////////////// COMMON
8045 EQUW &99,&A8 ;pointer to DDOS version information &A899
.P047
# if defined _DDOS316
8047 20 9A BA JSR SA9A
# elif defined _DDOS336
8047 20 88 BA JSR SA88
# elif defined _DDOS346
8047 20 AA BA JSR SAAA
# else
8047 20 A9 BA JSR SAA9
# endif
804A C9 01 CMP #&01
804C D0 07 BNE P055
804E C0 17 CPY #&17
8050 B0 02 BCS P054
8052 A0 17 LDY #&17
.P054
8054 60 RTS
.P055
8055 C9 02 CMP #&02
8057 D0 18 BNE P071
8059 98 TYA
805A 85 B1 STA &B1
805C 9D F0 0D STA &0DF0,X
805F A9 00 LDA #&00
8061 85 B0 STA &B0
8063 A0 C0 LDY #&C0
8065 91 B0 STA (&B0),Y
8067 C8 INY
8068 91 B0 STA (&B0),Y
806A A4 B1 LDY &B1
806C C8 INY
806D C8 INY
806E A9 02 LDA #&02
.P070
8070 60 RTS
.P071
8071 C9 03 CMP #&03
8073 D0 19 BNE P08E
8075 84 B3 STY &B3
8077 20 00 A3 JSR R300 ;save AXY
807A A9 7A LDA #&7A
807C 20 F4 FF JSR &FFF4
807F 8A TXA
8080 30 09 BMI P08B
8082 C9 32 CMP #&32
8084 D0 EA BNE P070
8086 A9 78 LDA #&78
8088 20 F4 FF JSR &FFF4
.P08B
808B 4C DB 81 JMP P1DB
.P08E
808E C9 04 CMP #&04
8090 D0 47 BNE P0D9
8092 20 00 A3 JSR R300 ;save AXY
8095 BA TSX
8096 86 B8 STX &B8
8098 98 TYA
8099 A2 5F LDX #&5F ;point XY to utility command table at &8E5F
809B A0 8E LDY #&8E
809D 20 C7 8E JSR PEC7 ;search for command in table
80A0 B0 4D BCS P0EF
80A2 86 AF STX &AF
80A4 98 TYA
80A5 48 PHA
80A6 AD 1E 02 LDA &021E
80A9 C9 2D CMP #&2D
80AB D0 22 BNE P0CF
80AD AD 1F 02 LDA &021F
80B0 C9 FF CMP #&FF
80B2 D0 1B BNE P0CF
80B4 20 14 A8 JSR R814 ;call OSBYTE &A8 = get ext. vector table addr
80B7 86 B0 STX &B0
80B9 84 B1 STY &B1
80BB A0 2D LDY #&2D
80BD B1 B0 LDA (&B0),Y
80BF C9 68 CMP #&68
80C1 D0 0C BNE P0CF
80C3 C8 INY
80C4 B1 B0 LDA (&B0),Y
80C6 C9 94 CMP #&94
80C8 D0 05 BNE P0CF
.P0CA
80CA 68 PLA
80CB A8 TAY
.P0CC
80CC 6C A8 00 JMP (&00A8)
.P0CF
80CF A6 AF LDX &AF
80D1 20 AA 00 JSR &00AA
80D4 10 F4 BPL P0CA
80D6 4C F2 84 JMP P4F2
.P0D9
80D9 C9 09 CMP #&09
80DB D0 30 BNE P10D
80DD 20 00 A3 JSR R300 ;save AXY
80E0 B1 F2 LDA (&F2),Y
80E2 C9 0D CMP #&0D
80E4 D0 0A BNE P0F0
80E6 A2 A7 LDX #&A7
80E8 A0 8E LDY #&8E
80EA A9 04 LDA #&04
80EC 20 F6 9F JSR QFF6
.P0EF
80EF 60 RTS
.P0F0
80F0 20 BB A4 JSR R4BB ;call GSINIT with C=0
80F3 F0 FA BEQ P0EF
80F5 98 TYA
80F6 48 PHA
80F7 A2 A7 LDX #&A7 ;point XY to *HELP keyword table at &8EA7
80F9 A0 8E LDY #&8E
80FB 20 C7 8E JSR PEC7 ;search for keyword in table
80FE B0 03 BCS P103 ;if keyword found
8100 20 CC 80 JSR P0CC ;then call its action address; print help
.P103
8103 68 PLA
8104 A8 TAY
.P105
8105 20 C5 FF JSR &FFC5
8108 90 FB BCC P105
810A 4C F0 80 JMP P0F0
#endif /* _DDOS357 */
.P10D
810D C9 0A CMP #&0A
810F D0 29 BNE P13A
8111 20 00 A3 JSR R300 ;Service call &0A = workspace claimed
8114 20 D4 9F JSR QFD4 ;set up pointer to private page
8117 A0 C1 LDY #&C1 ;y = offset = &C1 shared workspace ownership
8119 B1 B0 LDA (&B0),Y ;fetch byte at offset &C1 of private page
811B 10 1C BPL P139 ;if b7 clear then we already vacated, exit
811D A0 00 LDY #&00 ;else set offset = 0:
.P11F
811F C0 C0 CPY #&C0 ;store bytes &10C0..&11BF in private page
8121 90 05 BCC P128 ;(wrapped around so that private page
8123 B9 00 10 LDA &1000,Y ;contains: &1100..BF, &10C0..FF)
8126 B0 03 BCS P12B
.P128
8128 B9 00 11 LDA &1100,Y
.P12B
812B 91 B0 STA (&B0),Y
812D C8 INY
812E D0 EF BNE P11F
8130 20 D1 97 JSR Q7D1 ;ensure all files up-to-date on disc (flush)
8133 A0 C1 LDY #&C1 ;clear flag at offset &C1 of private page
8135 A9 00 LDA #&00 ;b7=1 iff we own the shared workspace.
8137 91 B0 STA (&B0),Y
.P139
8139 60 RTS
.P13A
813A C9 08 CMP #&08 ;if call not &1,2,3,4,8,9,A,FE,FF then return
813C D0 FB BNE P139
813E 20 29 A3 JSR R329 ;Service call &08 = unrecognised OSWORD
8141 A4 F0 LDY &F0 ;save XY (X will be clobbered on return)
8143 84 B0 STY &B0 ;set &B0..1 = pointer to OSWORD control block
8145 A4 F1 LDY &F1
8147 84 B1 STY &B1
8149 A4 EF LDY &EF ;set Y = OSWORD call number (in A on entry)
814B C0 7F CPY #&7F
814D D0 5C BNE P1AB
814F 20 C1 A7 JSR R7C1 ;OSWORD A = &7F
8152 A0 01 LDY #&01 ;claim NMI
8154 B1 B0 LDA (&B0),Y ;offset 1 = address LSB
8156 85 A6 STA &A6 ;copy to &A6
8158 C8 INY
8159 B1 B0 LDA (&B0),Y ;offset 2 = address 3MSB
815B 85 A7 STA &A7 ;copy to &A7
815D A0 00 LDY #&00
815F B1 B0 LDA (&B0),Y ;offset 0 = drive number
8161 30 03 BMI P166 ;if b7=1 then use previous drive
8163 20 03 A5 JSR R503 ;else select drive in A
.P166
8166 C8 INY ;offset 1 = address
8167 A2 02 LDX #&02
8169 20 CB 87 JSR P7CB ;copy address to &BE,F,&106F,70
816C C8 INY ;y = 5 on exit; increment
816D B1 B0 LDA (&B0),Y ;offset 6 = command
816F 29 3F AND #&3F
8171 85 B2 STA &B2
8173 20 67 A4 JSR R467 ;shift A right 4 places, extract bit 4:
8176 29 01 AND #&01 ;a=0 if writing to disc, A=1 if reading
8178 20 00 93 JSR Q300 ;open Tube data transfer channel
817B A0 07 LDY #&07
817D B1 B0 LDA (&B0),Y ;offset 7 = first parameter (usu. track)
817F C8 INY ;offset 8, Y points to second parameter
8180 85 BA STA &BA
8182 A2 FD LDX #&FD ;x = &FD to start at offset 0:
.P184
8184 E8 INX ;add 3 to X
8185 E8 INX
8186 E8 INX
8187 BD 11 B6 LDA &B611,X ;get command byte from table
818A F0 16 BEQ P1A2 ;if the terminator byte then exit
818C C5 B2 CMP &B2 ;else compare with OSWORD &7F command
818E D0 F4 BNE P184 ;if not the same try next entry
8190 08 PHP ;else save interrupt state
8191 58 CLI ;enable interrupts
8192 A9 81 LDA #&81 ;push return address &81A1 on stack
8194 48 PHA
8195 A9 A0 LDA #&A0
8197 48 PHA
8198 BD 13 B6 LDA &B613,X ;fetch action address high byte
819B 48 PHA ;push on stack
819C BD 12 B6 LDA &B612,X ;fetch action address low byte
819F 48 PHA ;push on stack
81A0 60 RTS ;jump to action address.
81A1 28 PLP ;Finish OSWORD &7F
.P1A2
81A2 20 A7 A7 JSR R7A7 ;release NMI
81A5 20 38 93 JSR Q338 ;release Tube
81A8 A9 00 LDA #&00 ;exit A=0 to claim service call
81AA 60 RTS
.P1AB
81AB C0 7D CPY #&7D ;OSWORD A <> &7F
81AD 90 2B BCC P1DA ;if A < &7D then exit
81AF 20 FB A4 JSR R4FB ;set current vol/dir = default, set up drive
81B2 20 9E 92 JSR Q29E ;load volume catalogue L4
81B5 C0 7E CPY #&7E
81B7 F0 09 BEQ P1C2
81B9 A0 00 LDY #&00 ;OSWORD A = &7D (and &80..&DF)
81BB AD 04 0F LDA &0F04 ;get catalogue cycle number
81BE 91 B0 STA (&B0),Y ;store in OSWORD control block offset 0
81C0 98 TYA ;return A = 0, claiming service call.
81C1 60 RTS
.P1C2
81C2 A9 00 LDA #&00 ;OSWORD A = &7E
81C4 A8 TAY ;get size of volume in bytes
81C5 91 B0 STA (&B0),Y ;store 0 at offset 0: multiple of 256 bytes
81C7 C8 INY ;offset 1
81C8 AD 07 0F LDA &0F07 ;get LSB volume size from catalogue
81CB 91 B0 STA (&B0),Y ;save as 3MSB volume size
81CD C8 INY ;offset 2
81CE AD 06 0F LDA &0F06 ;get boot option/top bits volume size
81D1 29 03 AND #&03 ;extract MSB volume size
81D3 91 B0 STA (&B0),Y ;save as 2MSB volume size
81D5 C8 INY ;offset 3
81D6 A9 00 LDA #&00 ;store 0: volume size less than 16 MiB
81D8 91 B0 STA (&B0),Y
.P1DA
81DA 60 RTS
.P1DB
81DB A5 B3 LDA &B3 ;get back boot flag (Y on entry to call &3)
81DD 48 PHA ;save on stack
81DE A2 FF LDX #&FF ;no error message being built print to screen
81E0 8E DD 10 STX &10DD
81E3 A9 FD LDA #&FD ;OSBYTE &FD = read/write type of last reset
81E5 20 1E A8 JSR R81E ;call OSBYTE with X=0, Y=&FF
81E8 20 02 82 JSR P202 ;validate shared workspace
81EB D0 03 BNE P1F0 ;if invalid then initialise shared workspace
81ED 8A TXA ;else test type of last reset
81EE F0 03 BEQ P1F3 ;if A=0 then soft break so skip
.P1F0
81F0 20 D2 82 JSR P2D2 ;else initialise shared workspace
.P1F3
81F3 20 84 A8 JSR R884 ;print DDOS banner
81F6 20 15 82 JSR P215 ;initialise DDOS
81F9 68 PLA ;if boot flag was >0
81FA D0 03 BNE P1FF ;then return A=0 to claim call
81FC 4C F5 82 JMP P2F5 ;else examine and boot default volume
.P1FF
81FF A9 00 LDA #&00
8201 60 RTS
.P202
8202 AD C2 10 LDA &10C2 ;Validate shared workspace
8205 C9 41 CMP #&41 ;compare first sentinel with "A"
8207 D0 05 BNE P20E ;return Z=0 if unequal
8209 AD DE 10 LDA &10DE ;else compare second sentinel with "H"
820C C9 48 CMP #&48 ;return Z=0 if unequal, Z=0 if both equal
.P20E
820E 60 RTS
#if defined _DDOS357
.P20F
#endif /* _DDOS357 */
;*DISC / *DISK
820F 48 PHA
8210 20 15 82 JSR P215 ;initialise DDOS
8213 68 PLA
8214 60 RTS
.P215
8215 A9 00 LDA #&00 ;Initialise DDOS
8217 BA TSX
8218 9D 08 01 STA &0108,X ;have A=0 returned on exit
821B A9 06 LDA #&06 ;FSC &06 = new FS about to change vectors
821D 20 42 80 JSR P042 ;issue Filing System Call
8220 A2 00 LDX #&00 ;x = 0 offset in MOS vector table
.P222
8222 BD 25 A8 LDA &A825,X ;copy addresses of extended vector handlers
8225 9D 12 02 STA &0212,X ;to FILEV,ARGSV,BGETV,BPUTV,GBPBV,FINDV,FSCV
8228 E8 INX ;loop until 7 vectors transferred
8229 E0 0E CPX #&0E
822B D0 F5 BNE P222
822D 20 14 A8 JSR R814 ;call OSBYTE &A8 = get ext. vector table addr
8230 84 B1 STY &B1 ;set up pointer to vector table
8232 86 B0 STX &B0
8234 A2 00 LDX #&00 ;x = 0 offset in DDOS vector table
8236 A0 1B LDY #&1B ;y = &1B offset of FILEV in extended vec tbl
.P238
8238 BD 33 A8 LDA &A833,X ;get LSB action address from table
823B 91 B0 STA (&B0),Y ;store in extended vector table
823D E8 INX
823E C8 INY
823F BD 33 A8 LDA &A833,X ;get MSB action address from table
8242 91 B0 STA (&B0),Y ;store in extended vector table
8244 E8 INX
8245 C8 INY
8246 A5 F4 LDA &F4 ;get our ROM slot number
8248 91 B0 STA (&B0),Y ;store in extended vector table
824A C8 INY
824B E0 0E CPX #&0E ;loop until 7 vectors transferred
824D D0 E9 BNE P238
824F A2 0F LDX #&0F ;service call &0F = vectors claimed
8251 20 18 A8 JSR R818 ;call OSBYTE &8F = issue service call
8254 A9 FF LDA #&FF
8256 8D 84 10 STA &1084 ;no catalogue in pages &0E..F
8259 20 D4 9F JSR QFD4 ;set up pointer to private page
825C A0 C0 LDY #&C0 ;test offset &C0 of private page
825E B1 B0 LDA (&B0),Y ;b7=1 if private page initialised
8260 10 35 BPL P297
8262 C8 INY ;test offset &C1 of private page
8263 B1 B0 LDA (&B0),Y ;b7=1 iff we own the shared workspace
8265 30 27 BMI P28E ;if we already own it then ensure wksp valid
8267 20 C5 9F JSR QFC5 ;else claim shared workspace
826A A0 00 LDY #&00
.P26C
826C B1 B0 LDA (&B0),Y ;restore bytes &10C0..&11BF from private page
826E C0 C0 CPY #&C0
8270 90 05 BCC P277
8272 99 00 10 STA &1000,Y
8275 B0 03 BCS P27A
.P277
8277 99 00 11 STA &1100,Y
.P27A
827A 88 DEY
827B D0 EF BNE P26C
827D A9 A0 LDA #&A0 ;set channel workspace pointer = &A0:
.P27F
827F A8 TAY ;transfer channel workspace pointer to Y
8280 48 PHA
8281 A9 3F LDA #&3F ;b7=0 PTR not in buffer; b6=0 buf unchanged
8283 20 46 99 JSR Q946 ;clear channel flag bits
8286 68 PLA
8287 99 1D 11 STA &111D,Y ;store workspace pointer in channel workspace
828A E9 1F SBC #&1F ;(clips MSB sector address) C=0 subtract &20
828C D0 F1 BNE P27F ;loop until all buffers discarded
.P28E
828E 20 02 82 JSR P202 ;validate shared workspace
8291 F0 03 BEQ P296 ;if invalid
8293 20 D2 82 JSR P2D2 ;then initialise shared workspace
.P296
8296 60 RTS
.P297
8297 A9 FF LDA #&FF ;set offset &C0 of private page = &FF
8299 91 B0 STA (&B0),Y ;b7=1 iff private page initialised
829B 8D C0 10 STA &10C0 ;set same flag in shared workspace
829E 20 C5 9F JSR QFC5 ;claim shared workspace
82A1 20 10 A8 JSR R810 ;call OSBYTE &EA = read Tube presence flag
82A4 8A TXA
82A5 49 FF EOR #&FF ;invert; 0=tube present &FF=Tube absent
82A7 8D D6 10 STA &10D6 ;save Tube presence flag
82AA 20 8E 82 JSR P28E ;ensure shared workspace is valid
82AD A9 0E LDA #&0E ;a=&0E
82AF 8D 01 10 STA &1001 ;*SROM E page in ROM slot 14 during disc ops
82B2 A0 00 LDY #&00 ;y=&00
82B4 8C C3 10 STY &10C3 ;no files are open
82B7 8C CE 10 STY &10CE ;unused
82BA 8C 87 10 STY &1087 ;NMI resource is not ours
82BD 88 DEY ;y=&FF
82BE 8C D2 10 STY &10D2 ;*commands are not *ENABLEd
82C1 8C D1 10 STY &10D1 ;*OPT 1,0 quiet operation
82C4 8C DD 10 STY &10DD ;no error message being built print to screen
82C7 8C 84 10 STY &1084 ;no catalogue in pages &0E..F
82CA 20 1C A8 JSR R81C ;call OSBYTE &FF = read/write startup options
82CD 86 B4 STX &B4 ;save them in zero page (used?)
82CF 4C 65 B6 JMP S665 ;re-read options and set drive stepping rate
.P2D2
82D2 A9 00 LDA #&00 ;Initialise shared workspace
82D4 8D E0 10 STA &10E0 ;*4080 OFF no double-stepping
82D7 8D CB 10 STA &10CB ;set default volume = "0A"
82DA 8D CD 10 STA &10CD ;set library volume = "0A"
82DD A9 24 LDA #&24
82DF 8D CA 10 STA &10CA ;set default directory = "$"
82E2 8D CC 10 STA &10CC ;set library directory = "$"
82E5 A9 80 LDA #&80
82E7 8D E3 10 STA &10E3 ;*DENSITY AUTO
82EA A9 41 LDA #&41 ;set &10C2 first sentinel = "A"
82EC 8D C2 10 STA &10C2
82EF A9 48 LDA #&48 ;set &10DE second sentinel = "H"
82F1 8D DE 10 STA &10DE
82F4 60 RTS
.P2F5
82F5 20 FB A4 JSR R4FB ;set current vol/dir = default, set up drive
82F8 20 A1 92 JSR Q2A1 ;load volume catalogue
82FB A0 00 LDY #&00
82FD A2 00 LDX #&00
82FF AD 06 0F LDA &0F06 ;get boot option/top bits volume size
8302 20 67 A4 JSR R467 ;shift A right 4 places
8305 F0 25 BEQ P32C ;if boot option = 0 then exit
8307 48 PHA
8308 A2 50 LDX #&50 ;point XY to filename "!BOOT"
830A A0 83 LDY #&83
830C 20 42 8F JSR PF42 ;set GSINIT pointer to XY, set Y=0
830F 20 E5 87 JSR P7E5 ;set current file from file spec
8312 20 63 89 JSR P963 ;search for file in catalogue
8315 68 PLA ;restore boot option
8316 B0 15 BCS P32D ;if !BOOT found then boot from it
8318 20 94 A3 JSR R394 ;else print "File not found" and return
831B EQUS "File not found"
8329 EQUB &0D
832A EQUB &0D
832B EA NOP
.P32C
832C 60 RTS
.P32D
832D C9 02 CMP #&02
832F 90 0E BCC P33F ;if boot option = 1 then load !BOOT
8331 F0 06 BEQ P339 ;if boot option = 2 then run !BOOT
8333 A2 4E LDX #&4E ;else boot option = 3 (or b7 or b6 set)
8335 A0 83 LDY #&83 ;point XY to "E.!BOOT"
8337 D0 0A BNE P343 ;call OSCLI
.P339
8339 A2 50 LDX #&50 ;point XY to "!BOOT"
833B A0 83 LDY #&83
833D D0 04 BNE P343 ;call OSCLI
.P33F
833F A2 46 LDX #&46 ;point XY to "L.!BOOT"
8341 A0 83 LDY #&83
.P343
8343 4C F7 FF JMP &FFF7 ;call OSCLI
8346 EQUS "L.!BOOT"
834D EQUB &0D
834E EQUS "E.!BOOT"
8355 EQUB &0D
;*TYPE
8356 20 D5 A2 JSR R2D5 ;claim service call and set up argument ptr
8359 A9 00 LDA #&00 ;a = &00 CR does not trigger line no.
835B F0 05 BEQ P362
;*LIST
835D 20 D5 A2 JSR R2D5 ;claim service call and set up argument ptr
8360 A9 FF LDA #&FF ;a = &FF CR triggers line number
.P362
8362 85 AB STA &AB ;store CR mask
8364 A9 40 LDA #&40 ;OSFIND &40 = open a file for reading
8366 20 CE FF JSR &FFCE ;call OSFIND
8369 A8 TAY ;test returned file handle
836A F0 30 BEQ P39C ;if file not found then raise error
836C A9 0D LDA #&0D ;preload CR so *LIST prints line no. 1
836E D0 1B BNE P38B ;branch to CR test (always)
.P370
8370 20 D7 FF JSR &FFD7 ;call OSBGET
8373 B0 1E BCS P393 ;if EOF then finish
8375 C9 0A CMP #&0A ;else if character is LF
8377 F0 F7 BEQ P370 ;ignore it and get next one
8379 28 PLP ;else restore result of (A & mask) - CR
837A D0 08 BNE P384 ;if no match just print the character
837C 48 PHA ;else save first character of line
837D 20 9F A2 JSR R29F ;increment and print BCD word
8380 20 CC A2 JSR R2CC ;print a space
8383 68 PLA ;restore first character
.P384
8384 20 E3 FF JSR &FFE3 ;call OSASCI
8387 24 FF BIT &FF ;if ESCAPE pressed
8389 30 09 BMI P394 ;then finish
.P38B
838B 25 AB AND &AB ;else apply mask to character just prt'd
838D C9 0D CMP #&0D ;compare masked character with CR
838F 08 PHP ;save result
8390 4C 70 83 JMP P370 ;and loop to read next character
.P393
8393 28 PLP ;discard result of (A & mask) - CR
.P394
8394 20 67 84 JSR P467 ;print newline
.P397
8397 A9 00 LDA #&00 ;OSFIND &00 = close file
8399 4C CE FF JMP &FFCE ;call OSFIND and exit
.P39C
839C 4C 43 89 JMP P943 ;raise "File not found" error
;*DUMP
839F 20 D5 A2 JSR R2D5 ;claim service call and set up argument ptr
83A2 A9 40 LDA #&40 ;OSFIND &40 = open a file for reading
83A4 20 CE FF JSR &FFCE ;call OSFIND
83A7 A8 TAY ;transfer file handle to Y
83A8 F0 F2 BEQ P39C ;if file not found raise error
83AA A6 F4 LDX &F4 ;else get our ROM slot number
83AC BD F0 0D LDA &0DF0,X ;get address of our private page
83AF 85 AD STA &AD ;set up pointer
83B1 E6 AD INC &AD ;point to second private page
.P3B3
83B3 24 FF BIT &FF ;if ESCAPE pressed
83B5 30 E0 BMI P397 ;then close file and exit
83B7 A5 A9 LDA &A9 ;else get high byte of file offset
83B9 20 29 A4 JSR R429 ;print hex byte
83BC A5 A8 LDA &A8 ;get low byte of file offset
83BE 20 29 A4 JSR R429 ;print hex byte
83C1 20 CC A2 JSR R2CC ;print a space
83C4 A9 07 LDA #&07 ;set counter, 8 bytes to print
83C6 85 AC STA &AC ;set up pointer
83C8 A2 00 LDX #&00 ;offset = 0 for indexed indirect load
.P3CA
83CA 20 D7 FF JSR &FFD7 ;call OSBGET
83CD B0 0D BCS P3DC ;if EOF then finish
83CF 81 AC STA (&AC,X) ;else store byte in 2nd private page
83D1 20 29 A4 JSR R429 ;print hex byte
83D4 20 CC A2 JSR R2CC ;print a space
83D7 C6 AC DEC &AC ;decrement counter
83D9 10 EF BPL P3CA ;loop until line complete
83DB 18 CLC ;c=0, end of file not reached
.P3DC
83DC 08 PHP ;save carry flag
83DD 90 0E BCC P3ED ;if not EOF then print full ASCII column
.P3DF
83DF 20 94 A3 JSR R394 ;else print "** "
83E2 EQUS "** "
83E5 A9 00 LDA #&00 ;clear rest of row with NULs
83E7 81 AC STA (&AC,X) ;to print dots in ASCII column
83E9 C6 AC DEC &AC ;decrement counter
83EB 10 F2 BPL P3DF ;loop until hex column complete
.P3ED
83ED A9 07 LDA #&07 ;set counter, 8 bytes to print
83EF 85 AC STA &AC ;set up pointer
.P3F1
83F1 A1 AC LDA (&AC,X) ;get saved byte from file
83F3 C9 7F CMP #&7F ;if DEL or higher
83F5 B0 04 BCS P3FB ;then print a dot
83F7 C9 20 CMP #&20 ;else if a printable character
83F9 B0 02 BCS P3FD ;then print it
.P3FB
83FB A9 2E LDA #&2E ;else print a dot:
.P3FD
83FD 20 E3 FF JSR &FFE3 ;call OSASCI
8400 C6 AC DEC &AC ;decrement counter
8402 10 ED BPL P3F1 ;loop until line complete
8404 20 67 84 JSR P467 ;print newline
8407 A9 08 LDA #&08 ;add 8 to file offset
8409 18 CLC
840A 65 A8 ADC &A8
840C 85 A8 STA &A8
840E 90 02 BCC P412
8410 E6 A9 INC &A9
.P412
8412 28 PLP ;restore carry flag from OSBGET
8413 90 9E BCC P3B3 ;if not at end of file then print next row
8415 B0 80 BCS P397 ;else close file and exit
;*BUILD
8417 20 D5 A2 JSR R2D5 ;claim service call and set up argument ptr
841A A9 80 LDA #&80 ;OSFIND &80 = open a file for writing
841C 20 CE FF JSR &FFCE ;call OSFIND
841F 85 AB STA &AB ;save file handle
.P421
8421 20 9F A2 JSR R29F ;increment and print BCD word
8424 20 CC A2 JSR R2CC ;print a space
8427 A6 F4 LDX &F4 ;get our ROM slot number
8429 BC F0 0D LDY &0DF0,X ;get address of our private page
842C C8 INY ;point to second private page
842D 84 AD STY &AD
842F A2 AC LDX #&AC ;x = &AC low address for OSWORD
8431 A0 FF LDY #&FF ;y = &FF
8433 84 AE STY &AE ;maximum line length = 255
8435 84 B0 STY &B0 ;maximum ASCII value = 255
8437 C8 INY
8438 84 AC STY &AC ;clear low byte of pointer
843A 84 AF STY &AF ;minimum ASCII value = 0
843C 98 TYA ;OSWORD &00 = read line of input
843D 20 F1 FF JSR &FFF1 ;call OSWORD
8440 08 PHP ;save returned flags
8441 84 AA STY &AA ;save length of line
8443 A4 AB LDY &AB ;y = file handle for OSBPUT
8445 A2 00 LDX #&00 ;offset = 0 for indexed indirect load
8447 F0 07 BEQ P450
.P449
8449 A1 AC LDA (&AC,X) ;get character of line
844B 20 D4 FF JSR &FFD4 ;call OSBPUT
844E E6 AC INC &AC ;increment low byte of pointer
.P450
8450 A5 AC LDA &AC ;get low byte of pointer
8452 C5 AA CMP &AA ;compare with length of line
8454 D0 F3 BNE P449 ;if not at end of line then loop
8456 28 PLP ;else restore flags from OSWORD
8457 B0 08 BCS P461 ;if user escaped from input then finish
8459 A9 0D LDA #&0D ;else A = carriage return
845B 20 D4 FF JSR &FFD4 ;write to file
845E 4C 21 84 JMP P421
.P461
8461 20 58 A4 JSR R458 ;acknowledge ESCAPE condition
8464 20 97 83 JSR P397 ;close file
.P467
8467 48 PHA ;Print newline
8468 A9 0D LDA #&0D
846A 20 03 A4 JSR R403 ;print character in A (OSASCI)
846D 68 PLA
846E 60 RTS
.P46F ;Select source volume
846F 20 00 A3 JSR R300 ;save AXY
8472 AE D3 10 LDX &10D3 ;set X = source volume
8475 A9 00 LDA #&00 ;a=&00 = we want source disc
8477 F0 08 BEQ P481 ;branch (always)
.P479 ;Select destination volume
8479 20 00 A3 JSR R300 ;save AXY
847C AE D4 10 LDX &10D4 ;set X = destination volume
847F A9 80 LDA #&80 ;a=&80 = we want destination disc
.P481
8481 48 PHA ;save A
8482 86 CF STX &CF ;set wanted volume as current volume
8484 20 D6 A7 JSR R7D6 ;set up for current drive
8487 68 PLA ;restore A
8488 24 A9 BIT &A9 ;if disc swapping required
848A 30 01 BMI P48D ;then branch to prompt
.P48C
848C 60 RTS ;else exit
.P48D
848D C5 AA CMP &AA ;compare wanted disc with disc in drive
848F F0 FB BEQ P48C ;if the same then do not prompt
8491 85 AA STA &AA ;else the drive will contain the disc we want
8493 20 94 A3 JSR R394 ;print "Insert "
8496 EQUS "Insert "
849D EA NOP
849E 24 AA BIT &AA ;if b7=1
84A0 30 0B BMI P4AD ;then print "destination"
84A2 20 94 A3 JSR R394 ;else print "source"
84A5 EQUS "source"
84AB 90 0F BCC P4BC ;and branch (always)
.P4AD
84AD 20 94 A3 JSR R394
84B0 EQUS "destination"
84BB EA NOP
.P4BC
84BC 20 94 A3 JSR R394 ;print " disk and hit a key"
84BF EQUS " disk and hit a key"
84D2 EA NOP
84D3 20 EA 84 JSR P4EA
84D6 4C 67 84 JMP P467 ;print newline and exit
.P4D9 ;Ask user yes or no
84D9 20 EA 84 JSR P4EA ;wait for keypress
84DC 29 5F AND #&5F ;convert to uppercase
84DE C9 59 CMP #&59 ;is it "Y"?
84E0 08 PHP ;save the answer
84E1 F0 02 BEQ P4E5 ;if so then print "Y"
84E3 A9 4E LDA #&4E ;else print "N"
.P4E5
84E5 20 03 A4 JSR R403 ;print character in A (OSASCI)
84E8 28 PLP ;return Z=1 if "Y" or "y" pressed
84E9 60 RTS
.P4EA
84EA 20 EE A7 JSR R7EE ;call *FX 15,1 = clear input buffer
84ED 20 E0 FF JSR &FFE0 ;call OSRDCH, wait for input character
84F0 90 03 BCC P4F5 ;if ESCAPE was pressed
.P4F2
84F2 A6 B8 LDX &B8 ;then abort our routine
84F4 9A TXS ;clear our stacked items, return to caller
.P4F5
84F5 60 RTS
.P4F6 ;Restore parameters of source drive
84F6 A0 05 LDY #&05 ;use slot of invalid channel &16
84F8 D0 02 BNE P4FC ;restore drive parameters of open file
.P4FA ;Restore parameters of destination drive
84FA A0 06 LDY #&06 ;use slot of invalid channel &17:
.P4FC ;Restore drive parameters of open file
84FC 20 2C 85 JSR P52C ;multiply Y by 6
84FF A2 00 LDX #&00
.P501
8501 B9 E6 10 LDA &10E6,Y ;copy from parameter set &10E6..B,Y
8504 9D E0 10 STA &10E0,X ;to current drive parameters &10E0..5
8507 C8 INY
8508 E8 INX
8509 E0 06 CPX #&06 ;loop until 6 bytes copied
850B D0 F4 BNE P501
850D 60 RTS
.P50E ;Save parameters of source drive
850E 20 00 A3 JSR R300 ;save AXY
8511 A0 05 LDY #&05 ;use slot of invalid channel &16
8513 D0 05 BNE P51A ;save drive parameters of open file
.P515 ;Save parameters of destination drive
8515 20 00 A3 JSR R300 ;save AXY
8518 A0 06 LDY #&06 ;use slot of invalid channel &17:
.P51A ;Save drive parameters of open file
851A 20 2C 85 JSR P52C ;multiply Y by 6
851D A2 00 LDX #&00
.P51F
851F BD E0 10 LDA &10E0,X ;copy from current drive parameters &10E0..5
8522 99 E6 10 STA &10E6,Y ;to parameter set &10E6..B,Y
8525 C8 INY
8526 E8 INX
8527 E0 06 CPX #&06 ;loop until 6 bytes copied
8529 D0 F4 BNE P51F
852B 60 RTS
.P52C ;Multiply Y by 6
852C A5 A8 LDA &A8 ;save content of &A8
852E 48 PHA
852F 98 TYA ;a=y
8530 85 A8 STA &A8 ;save in temp
8532 0A ASL A ;multiply A by two
8533 65 A8 ADC &A8 ;add starting value making 3x
8535 0A ASL A ;double the result making 6x
8536 A8 TAY ;put back in Y
8537 68 PLA ;restore content of &A8
8538 85 A8 STA &A8
853A 60 RTS
;*BACKUP
853B 20 3A A2 JSR R23A ;ensure *ENABLE active
853E 20 4F A2 JSR R24F ;parse and print source and dest. volumes
8541 A9 00 LDA #&00
8543 85 A8 STA &A8
8545 85 C8 STA &C8
8547 85 C9 STA &C9
8549 85 CA STA &CA
854B 85 CB STA &CB
854D 20 38 86 JSR P638 ;load source volume catalogue
8550 A9 00 LDA #&00
8552 8D E2 10 STA &10E2 ;data area starts on track 0
8555 20 0E 85 JSR P50E ;save parameters of source drive
8558 20 19 86 JSR P619 ;return volume size in XY/boot option in A
855B 8D D7 10 STA &10D7 ;save source volume boot option
855E 86 C6 STX &C6
8560 84 C7 STY &C7
8562 20 32 86 JSR P632 ;load destination volume catalogue
8565 A9 00 LDA #&00
8567 8D E2 10 STA &10E2 ;data area starts on track 0
856A 20 15 85 JSR P515 ;save parameters of destination drive
856D AD 07 11 LDA &1107 ;get density of source drive
8570 4D 0D 11 EOR &110D ;xor with density flag of destination drive
8573 29 40 AND #&40 ;extract bit 6 density flag, ignore auto b7
8575 F0 3A BEQ P5B1 ;if the same density then skip
8577 A9 D5 LDA #&D5 ;else error number = &D5
8579 20 EF A3 JSR R3EF ;begin error message, number in A
857C 20 8A A3 JSR R38A ;print error message
857F EQUS "Both disks MUST be same density"
859E EQUB &0D
859F EQUB &0A
85A0 EQUS "Hint...use MCOPY"
85B0 EQUB &00 ;terminator byte &00 raises error
.P5B1
85B1 20 19 86 JSR P619 ;return volume size in XY/boot option in A
85B4 8A TXA ;save destination volume size on stack
85B5 48 PHA
85B6 98 TYA
85B7 48 PHA
85B8 C5 C7 CMP &C7 ;compare MSBs dest volume size - source
85BA 90 07 BCC P5C3 ;if dest < source then raise error
85BC D0 29 BNE P5E7 ;if dest > source then proceed
85BE 8A TXA ;else compare LSBs dest - source
85BF C5 C6 CMP &C6
85C1 B0 24 BCS P5E7 ;if dest >= source then proceed
.P5C3
85C3 A9 D5 LDA #&D5 ;else error number = &D5
85C5 20 EF A3 JSR R3EF ;begin error message, number in A
85C8 AD D3 10 LDA &10D3 ;get source drive
85CB 20 08 8D JSR PD08 ;print " Drive " plus volume spec in A
85CE 20 94 A3 JSR R394 ;print " larger than "
85D1 EQUS " larger than "
85DE AD D4 10 LDA &10D4 ;get destination drive
85E1 20 08 8D JSR PD08 ;print " Drive " plus volume spec in A
85E4 4C B9 A3 JMP R3B9 ;terminate error message, raise error
.P5E7
85E7 20 51 87 JSR P751 ;copy source drive/file to destination
85EA 2C E3 10 BIT &10E3 ;test density flag
85ED 70 19 BVS P608 ;if double density then update disc catalogue
85EF 20 79 84 JSR P479 ;else select destination volume
85F2 20 A1 92 JSR Q2A1 ;load volume catalogue
85F5 68 PLA ;pop MSB destination volume size
85F6 29 0F AND #&0F ;mask bits 0..3
85F8 0D D7 10 ORA &10D7 ;apply source boot option in bits 4..5
85FB 8D 06 0F STA &0F06 ;store in catalogue
85FE 68 PLA ;pop LSB destination volume size
85FF 8D 07 0F STA &0F07 ;store in catalogue
8602 20 81 92 JSR Q281 ;write volume catalogue
8605 4C BA 86 JMP P6BA ;and do a NEW for BASIC
;[BUG] Copying a 40 track DD disc to an 80 track DD disc preserves
;the destination disc size at &1001..2 = 1440 sectors but copies
;the source track count at &1004 = 40 tracks. EDOS *CATGEN will be
;unable to assign tracks in the second half of the disc.
.P608 ;Update disc catalogue
8608 20 D9 A6 JSR R6D9 ;load disc catalogue L3
860B 68 PLA ;pop MSB disc size
860C 8D 01 0E STA &0E01 ;store in disc catalogue
860F 68 PLA ;pop LSB disc size
8610 8D 02 0E STA &0E02 ;store in disc catalogue
8613 20 DD A6 JSR R6DD ;write disc catalogue L3
8616 4C BA 86 JMP P6BA ;and do a NEW for BASIC
.P619 ;Return volume size in XY/boot option in A
8619 AE 07 0F LDX &0F07 ;get LSB volume size from catalogue
861C AD 06 0F LDA &0F06 ;get boot option/top bits volume size
861F 48 PHA
8620 29 03 AND #&03 ;extract MSB volume size
8622 A8 TAY ;put volume size in XY
8623 2C E3 10 BIT &10E3 ;test density flag
8626 50 06 BVC P62E ;if double density
8628 AE 0F 10 LDX &100F ;then load disc size from workspace instead
862B AC 0E 10 LDY &100E
.P62E
862E 68 PLA ;return disc size in XY
862F 29 F0 AND #&F0 ;return boot option in A bits 5 and 4
8631 60 RTS
.P632 ;Load destination volume catalogue
8632 20 79 84 JSR P479 ;select destination volume
8635 4C A1 92 JMP Q2A1 ;load volume catalogue
.P638 ;Load source volume catalogue
8638 20 6F 84 JSR P46F ;select source volume
863B 4C A1 92 JMP Q2A1 ;load volume catalogue
;*COPY
863E 20 2B 89 JSR P92B ;allow wildcard characters in filename
8641 20 4F A2 JSR R24F ;parse and print source and dest. volumes
8644 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
8647 20 E5 87 JSR P7E5 ;set current file from file spec
864A 20 6F 84 JSR P46F ;select source volume
864D 20 3E 89 JSR P93E ;ensure matching file in catalogue
8650 20 0E 85 JSR P50E ;save parameters of source drive
.P653
8653 84 AB STY &AB ;save cat. offset of found file in zero page
8655 20 C0 89 JSR P9C0 ;print *INFO line
8658 A2 00 LDX #&00
.P65A
865A B5 C7 LDA &C7,X ;save file spec in workspace
865C 9D 58 10 STA &1058,X
865F B9 08 0E LDA &0E08,Y ;copy matching filename+dir to current file
8662 95 C7 STA &C7,X
8664 9D 50 10 STA &1050,X ;and to workspace
8667 B9 08 0F LDA &0F08,Y ;copy matching file's catalogue information
866A 95 BD STA &BD,X ;to OSFILE block?
866C 9D 47 10 STA &1047,X ;and to workspace
866F E8 INX
8670 C8 INY
8671 E0 08 CPX #&08 ;loop until 8 bytes of each field copied
8673 D0 E5 BNE P65A
8675 A5 C3 LDA &C3 ;get top bits exec/length/load/start sector
8677 20 5F A4 JSR R45F ;extract b5,b4 of A
867A 85 C5 STA &C5
867C A5 C1 LDA &C1 ;get MSB length
867E 18 CLC
867F 69 FF ADC #&FF ;set C=1 iff file includes partial sector
8681 A5 C2 LDA &C2 ;get 2MSB length
8683 69 00 ADC #&00 ;round up to get LSB length in sectors
8685 85 C6 STA &C6
8687 A5 C5 LDA &C5 ;get extracted MSB length
8689 69 00 ADC #&00 ;carry out to get MSB length in sectors
868B 85 C7 STA &C7
868D AD 4E 10 LDA &104E ;get LSB start LBA (also at &C4)
8690 85 C8 STA &C8
8692 AD 4D 10 LDA &104D ;get top bits exec/length/load/start sector
8695 29 03 AND #&03 ;extract b1,b0 of A
8697 85 C9 STA &C9 ;store MSB start LBA
8699 A9 FF LDA #&FF
869B 85 A8 STA &A8
869D 20 51 87 JSR P751 ;copy source drive/file to destination
86A0 20 6F 84 JSR P46F ;select source volume
86A3 20 9E 92 JSR Q29E ;load volume catalogue L4
86A6 A2 07 LDX #&07
.P6A8
86A8 BD 58 10 LDA &1058,X ;restore file spec to current file
86AB 95 C7 STA &C7,X
86AD CA DEX
86AE 10 F8 BPL P6A8 ;loop until 8 characters copied
86B0 A4 AB LDY &AB ;restore cat. offset of found file
86B2 8C CF 10 STY &10CF ;to workspace
86B5 20 6A 89 JSR P96A ;find next matching file
86B8 B0 99 BCS P653 ;loop while match found, else:
.P6BA ;Store empty BASIC program at OSHWM (NEW)
86BA AD 89 10 LDA &1089 ;get start of user memory
86BD 85 BF STA &BF ;store as high byte of pointer
86BF A9 00 LDA #&00 ;clear low byte
86C1 85 BE STA &BE ;PAGE is always on a page boundary
86C3 A9 0D LDA #&0D ;&0D = first byte of end-of-program marker
86C5 91 BE STA (&BE),Y ;store at start of user memory
86C7 C8 INY ;&FF = second byte of end-of-program marker
86C8 A9 FF LDA #&FF ;store in user memory
86CA 91 BE STA (&BE),Y ;(where is Y set to zero, though?)
86CC 60 RTS
.P6CD
86CD 20 09 87 JSR P709 ;swap &BC..CD with &1045..56
86D0 20 79 84 JSR P479 ;select destination volume
86D3 A5 CE LDA &CE ;save current directory
86D5 48 PHA
86D6 20 9E 92 JSR Q29E ;load volume catalogue L4
86D9 20 63 89 JSR P963 ;search for file in catalogue
86DC 90 03 BCC P6E1 ;if found
86DE 20 9E 89 JSR P99E ;then delete catalogue entry
.P6E1
86E1 68 PLA ;restore current directory
86E2 85 CE STA &CE ;set as current directory
86E4 20 15 85 JSR P515 ;save parameters of destination drive
86E7 20 19 92 JSR Q219 ;expand 18-bit load address to 32-bit
86EA 20 35 92 JSR Q235 ;expand 18-bit exec address to 32-bit
86ED A5 C4 LDA &C4
86EF 20 5F A4 JSR R45F ;extract b5,b4 of A
86F2 85 C6 STA &C6
86F4 20 2C 91 JSR Q12C ;create catalogue entry
86F7 A5 C4 LDA &C4
86F9 29 03 AND #&03
86FB 48 PHA
86FC A5 C5 LDA &C5
86FE 48 PHA
86FF 20 09 87 JSR P709 ;swap &BC..CD with &1045..56
8702 68 PLA
8703 85 CA STA &CA
8705 68 PLA
8706 85 CB STA &CB
8708 60 RTS
.P709 ;Swap &BC..CD with &1045..56
8709 A2 11 LDX #&11
.P70B
870B BD 45 10 LDA &1045,X
870E B4 BC LDY &BC,X
8710 95 BC STA &BC,X
8712 98 TYA
8713 9D 45 10 STA &1045,X
8716 CA DEX
8717 10 F2 BPL P70B
8719 60 RTS
;unreachable code
871A 20 6F 84 JSR P46F ;select source volume
871D 20 A1 92 JSR Q2A1 ;load volume catalogue
8720 20 0E 85 JSR P50E ;save parameters of source drive
8723 AD 07 0F LDA &0F07 ;get LSB volume size
8726 85 C6 STA &C6 ;store in zero page
8728 AD 06 0F LDA &0F06 ;get boot option/top bits volume size
872B 29 03 AND #&03 ;extract MSB volume size
872D 85 C7 STA &C7 ;store in zero page
872F AD 06 0F LDA &0F06 ;get boot option/top bits volume size
8732 29 F0 AND #&F0 ;extract boot option to b7..4
8734 8D D7 10 STA &10D7 ;store in workspace
8737 20 79 84 JSR P479 ;select destination volume
873A 20 A1 92 JSR Q2A1 ;load volume catalogue
873D 4C 15 85 JMP P515 ;save parameters of destination drive
;unreachable code
;compare new volume size - old volume size
8740 AD 06 0F LDA &0F06 ;get boot option/top bits volume size
8743 29 03 AND #&03 ;extract MSB volume size
8745 C5 C7 CMP &C7 ;compare with stored MSB volume size
8747 90 07 BCC P750 ;return C=0, Z=0 if new size < old size
8749 D0 05 BNE P750 ;return C=1, Z=0 if new size > old size
874B AD 07 0F LDA &0F07 ;if MSBs equal, load LSB old size
874E C5 C6 CMP &C6 ;return C=1, Z=1 if sizes equal, or as above
.P750
8750 60 RTS
.P751 ;Copy source drive/file to destination
8751 A9 00 LDA #&00
8753 85 BE STA &BE
8755 85 C2 STA &C2 ;set LSB transfer size = 0
.P757
8757 A5 C6 LDA &C6 ;compare remaining file size - available memory
8759 A8 TAY
875A CD 8B 10 CMP &108B
875D A5 C7 LDA &C7
875F E9 00 SBC #&00
8761 90 03 BCC P766 ;if remainder fits then Y=file size in pages
8763 AC 8B 10 LDY &108B ;else Y=size of available memory in pages
.P766
8766 84 C3 STY &C3 ;set MSB transfer size = no. pages in Y
8768 A5 C8 LDA &C8
876A 85 C5 STA &C5
876C A5 C9 LDA &C9
876E 85 C4 STA &C4
8770 AD 89 10 LDA &1089
8773 85 BF STA &BF
8775 20 F6 84 JSR P4F6 ;restore parameters of source drive
8778 20 6F 84 JSR P46F ;select source volume
877B 20 28 92 JSR Q228 ;set high word of OSFILE load address = &FFFF
877E 20 1D 90 JSR Q01D ;read extended file L5
8781 24 A8 BIT &A8
8783 10 07 BPL P78C
8785 20 CD 86 JSR P6CD
8788 A9 00 LDA #&00
878A 85 A8 STA &A8
.P78C
878C A5 CA LDA &CA
878E 85 C5 STA &C5
8790 A5 CB LDA &CB
8792 85 C4 STA &C4
8794 AD 89 10 LDA &1089
8797 85 BF STA &BF
8799 20 FA 84 JSR P4FA ;restore parameters of destination drive
879C 20 79 84 JSR P479 ;select destination volume
879F 20 28 92 JSR Q228 ;set high word of OSFILE load address = &FFFF
87A2 20 23 90 JSR Q023 ;write extended file L5
87A5 A5 C3 LDA &C3
87A7 18 CLC
87A8 65 CA ADC &CA
87AA 85 CA STA &CA
87AC 90 02 BCC P7B0
87AE E6 CB INC &CB
.P7B0
87B0 A5 C3 LDA &C3
87B2 18 CLC
87B3 65 C8 ADC &C8
87B5 85 C8 STA &C8
87B7 90 02 BCC P7BB
87B9 E6 C9 INC &C9
.P7BB
87BB 38 SEC
87BC A5 C6 LDA &C6 ;get LSB remaining size of file in sectors
87BE E5 C3 SBC &C3 ;subtract number of pages transferred
87C0 85 C6 STA &C6 ;update LSB remaining size
87C2 B0 02 BCS P7C6
87C4 C6 C7 DEC &C7 ;borrow in from MSB remaining size if req'd
.P7C6
87C6 05 C7 ORA &C7 ;or MSB with LSB, Z=0 if pages remain
87C8 D0 8D BNE P757 ;if file transfer is incomplete then loop
87CA 60 RTS
.P7CB
87CB 20 DB 87 JSR P7DB ;Copy address to (&BC,D,&106D,E)+X
87CE CA DEX
87CF CA DEX
87D0 20 D3 87 JSR P7D3
.P7D3
87D3 B1 B0 LDA (&B0),Y
87D5 9D 6D 10 STA &106D,X
87D8 E8 INX
87D9 C8 INY
87DA 60 RTS
.P7DB
87DB 20 DE 87 JSR P7DE
.P7DE
87DE B1 B0 LDA (&B0),Y
87E0 95 BC STA &BC,X
87E2 E8 INX
87E3 C8 INY
87E4 60 RTS
.P7E5 ;Set current file from file spec
87E5 20 F0 A4 JSR R4F0 ;set current volume and dir = default
87E8 4C FB 87 JMP P7FB ;parse file spec
.P7EB ;Set current file from argument pointer
87EB 20 F0 A4 JSR R4F0 ;set current volume and dir = default:
.P7EE ;Parse file spec from argument pointer
87EE A5 BC LDA &BC ;copy argument pointer to GSINIT pointer
87F0 85 F2 STA &F2
87F2 A5 BD LDA &BD
87F4 85 F3 STA &F3
87F6 A0 00 LDY #&00 ;set Y = 0 offset for GSINIT
87F8 20 BB A4 JSR R4BB ;call GSINIT with C=0:
.P7FB ;Parse file spec
87FB 20 66 88 JSR P866 ;set current filename to all spaces
87FE 20 C5 FF JSR &FFC5 ;call GSREAD
8801 B0 53 BCS P856 ;if argument empty then "Bad filename"
8803 C9 3A CMP #&3A ;else is first character ":"?
8805 D0 22 BNE P829 ;if not then skip to dir/filename
8807 20 C5 FF JSR &FFC5 ;else a drive is specified, call GSREAD
880A B0 57 BCS P863 ;if no drive number then "Bad drive"
880C 20 BF A4 JSR R4BF ;else set current drive from ASCII digit
880F 20 C5 FF JSR &FFC5 ;call GSREAD
8812 B0 42 BCS P856 ;if only drive specified then "Bad filename"
8814 C9 2E CMP #&2E ;else if next character is "."
8816 F0 0C BEQ P824 ;then get first character of filename
8818 20 CB A4 JSR R4CB ;else set volume from ASCII letter
881B 20 C5 FF JSR &FFC5 ;call GSREAD
881E B0 36 BCS P856 ;if only volume spec'd then "Bad filename"
8820 C9 2E CMP #&2E ;if separator character "." missing
8822 D0 32 BNE P856 ;then raise "Bad filename" error
.P824
8824 20 C5 FF JSR &FFC5 ;call GSREAD, get first character of filename
8827 B0 2D BCS P856 ;if filename is empty then "Bad filename"
.P829
8829 85 C7 STA &C7 ;else save first character of filename
882B A2 00 LDX #&00 ;set filename offset = 0
882D 20 C5 FF JSR &FFC5 ;call GSREAD, get second filename character
#if defined _BUGFIX
8830 B0 3A BCS P86C ;if absent then process one-character name
#else
8830 B0 44 BCS P876 ;if absent then process one-character name
#endif
8832 E8 INX ;else offset = 1
8833 C9 2E CMP #&2E ;is the second character "."?
8835 D0 0B BNE P842 ;if not then read in rest of leaf name
8837 A5 C7 LDA &C7 ;else first character was a directory spec
8839 20 80 A5 JSR R580 ;set directory from ASCII character
883C 20 C5 FF JSR &FFC5 ;call GSREAD, get first character of leaf name
883F B0 15 BCS P856 ;if leaf name is empty then "Bad filename"
8841 CA DEX ;else offset = 0, read in leaf name:
.P842
8842 C9 2A CMP #&2A ;is filename character "*"?
8844 F0 36 BEQ P87C ;if so then process "*" in filename
8846 C9 21 CMP #&21 ;else is it a control character or space?
8848 90 0C BCC P856 ;if so then raise "Bad filename" error
884A 95 C7 STA &C7,X ;else store character of filename
884C E8 INX ;point X to next character of current filename
884D 20 C5 FF JSR &FFC5 ;call GSREAD, get next character of leaf name
#if defined _BUGFIX
8850 B0 29 BCS P87B ;if no more then filename complete, return
#else
8850 B0 23 BCS P875 ;if no more then filename complete, return
#endif
8852 E0 07 CPX #&07 ;else have seven characters been read already?
8854 D0 EC BNE P842 ;if not then loop, else:
.P856 ;Raise "Bad filename" error.
8856 20 51 A3 JSR R351
8859 EQUB &CC
885A EQUS "filename"
8862 EQUB &00
.P863
8863 4C 11 A5 JMP R511 ;Raise "Bad drive" error.
.P866 ;Set current filename to all spaces
8866 A2 00 LDX #&00
8868 A9 20 LDA #&20
#if defined _BUGFIX
886A D0 08 BNE P874 ;branch (always)
.P86C ;Process one-character filename
886C A5 C7 LDA &C7 ;if filename is "*", then:
886E C9 2A CMP #&2A
8870 D0 09 BNE P87B
.P872 ;Pad current filename with "#"s
8872 A9 23 LDA #&23 ;x=offset of end of filename
.P874
8874 95 C7 STA &C7,X
8876 E8 INX
8877 E0 07 CPX #&07
8879 D0 F9 BNE P874
.P87B
887B 60 RTS
.P87C ;Process "*" in filename
887C 20 C5 FF JSR &FFC5 ;call GSREAD
887F B0 F1 BCS P872 ;if end of argument pad filename with "#"s
8881 C9 20 CMP #&20 ;else if next character is space
8883 F0 ED BEQ P872 ;then pad filename with "#"s
8885 D0 CF BNE P856 ;else raise "Bad filename" error.
#else /* _BUGFIX */
886A D0 02 BNE P86E ;branch (always)
.P86C ;Pad current filename with "#"s
886C A9 23 LDA #&23 ;x=offset of end of filename
.P86E
886E 95 C7 STA &C7,X
8870 E8 INX
8871 E0 07 CPX #&07
8873 D0 F9 BNE P86E
.P875
8875 60 RTS
.P876 ;Process one-character filename
8876 A5 C7 LDA &C7 ;if filename is "*", then:
8878 C9 2A CMP #&2A ;([BUG] don't call GSREAD twice on end-of-str
887A D0 F9 BNE P875 ;e.g. *INFO"*" results in "Bad string" error)
.P87C ;Process "*" in filename
887C 20 C5 FF JSR &FFC5 ;call GSREAD
887F B0 EB BCS P86C ;if end of argument pad filename with "#"s
8881 C9 20 CMP #&20 ;else if next character is space
8883 F0 E7 BEQ P86C ;then pad filename with "#"s
8885 D0 CF BNE P856 ;else raise "Bad filename" error.
#endif /* _BUGFIX */
.P887 ;Ensure disc not changed
8887 20 00 A3 JSR R300 ;save AXY
888A AD 04 0F LDA &0F04 ;get cycle number of last catalogue read
888D 20 9E 92 JSR Q29E ;load volume catalogue L4
8890 CD 04 0F CMP &0F04 ;compare with freshly loaded cycle number
#if defined _BUGFIX
8893 F0 E6 BEQ P87B ;return if equal, else:
#else
8893 F0 E0 BEQ P875 ;return if equal, else:
#endif
.P895 ;Raise "Disk changed" error.
8895 20 62 A3 JSR R362
8898 EQUB &C8
8899 EQUS "Disk changed"
88A5 EQUB &00
.P8A6 ;Print filename from catalogue
88A6 20 00 A3 JSR R300 ;save AXY
88A9 B9 0F 0E LDA &0E0F,Y ;get directory character
88AC 08 PHP ;save N = lock attribute
88AD 29 7F AND #&7F ;extract ASCII character
88AF D0 05 BNE P8B6 ;if NUL then file is in CSD
88B1 20 C9 A2 JSR R2C9 ;so print two spaces
88B4 F0 06 BEQ P8BC ;branch (always)
.P8B6
88B6 20 03 A4 JSR R403 ;else print directory character
88B9 20 01 A4 JSR R401 ;print a dot
.P8BC
88BC A2 06 LDX #&06 ;repeat 7 times:
.P8BE
88BE B9 08 0E LDA &0E08,Y ;get character of leaf name
88C1 29 7F AND #&7F ;mask bit 7
88C3 20 03 A4 JSR R403 ;print character
88C6 C8 INY
88C7 CA DEX
88C8 10 F4 BPL P8BE ;and loop
88CA 20 C9 A2 JSR R2C9 ;print two spaces
88CD A9 20 LDA #&20 ;a = space
88CF 28 PLP ;restore lock attribute in N
88D0 10 02 BPL P8D4 ;if lock bit set
88D2 A9 4C LDA #&4C ;then A = capital L
.P8D4
88D4 20 03 A4 JSR R403 ;print attribute character
88D7 4C CC A2 JMP R2CC ;print a space and exit
.P8DA ;Print number of spaces in Y
88DA 20 CC A2 JSR R2CC ;print a space
88DD 88 DEY ;loop until Y = 0
88DE D0 FA BNE P8DA
88E0 60 RTS
.P8E1 ;Prepare extended file transfer
88E1 A9 00 LDA #&00 ;set MSB length = 0; transfer less than 64 KiB
88E3 85 A5 STA &A5
88E5 A6 C4 LDX &C4 ;x = LSB of relative LBA
88E7 4C F6 88 JMP P8F6
.P8EA ;Prepare ordinary file transfer
88EA A5 C4 LDA &C4 ;get top bits exec/length/load/start sector
88EC 20 5F A4 JSR R45F ;extract b5,b4 of A
88EF 85 A5 STA &A5 ;?&A5 = b17..16 (MSB) of length
88F1 A5 C4 LDA &C4 ;x = b9..8 (MSB) of relative LBA
88F3 29 03 AND #&03
88F5 AA TAX
.P8F6
88F6 A5 BE LDA &BE ;copy user data address to NMI area
88F8 85 A6 STA &A6
88FA A5 BF LDA &BF
88FC 85 A7 STA &A7
88FE A5 C3 LDA &C3 ;copy 2MSB length
8900 85 A4 STA &A4
8902 A5 C2 LDA &C2 ;copy LSB length
8904 85 A3 STA &A3
8906 86 BA STX &BA ;store LSB/MSB of LBA (clobbered if LSB)
8908 A5 C5 LDA &C5 ;copy MSB/LSB of LBA
890A 85 BB STA &BB
890C AD E1 10 LDA &10E1 ;get number of sectors per track
890F F0 19 BEQ P92A ;if not defined then just use the LBA
8911 AD E2 10 LDA &10E2 ;else get first track of current volume
8914 85 BA STA &BA ;set track number for transfer
8916 C6 BA DEC &BA ;decrement, to increment at start of loop
8918 A5 C5 LDA &C5 ;get LSB of relative LBA:
.P91A
891A 38 SEC ;set C=1 to subtract without borrow:
.P91B
891B E6 BA INC &BA ;increment track number
891D ED E1 10 SBC &10E1 ;subtract sectors-per-track from LBA
8920 B0 F9 BCS P91B ;loop until LSB borrows in
8922 CA DEX ;then decrement MSB of relative LBA
8923 10 F5 BPL P91A ;loop until MSB borrows in/underflows
8925 6D E1 10 ADC &10E1 ;add sectors per track to negative remainder
8928 85 BB STA &BB ;set sector number.
.P92A
892A 60 RTS
.P92B ;Allow wildcard characters in filename
892B A9 23 LDA #&23
892D D0 02 BNE P931
.P92F ;Disallow wildcard characters in filename
892F A9 FF LDA #&FF
.P931
8931 8D D0 10 STA &10D0
8934 60 RTS
.P935 ;Ensure file matching spec in catalogue
8935 20 E5 87 JSR P7E5 ;set current file from file spec
8938 4C 3E 89 JMP P93E ;ensure matching file in catalogue
.P93B ;Ensure file matching argument in catalogue
893B 20 EB 87 JSR P7EB ;set current file from argument pointer:
.P93E ;Ensure matching file in catalogue
893E 20 63 89 JSR P963 ;search for file in catalogue
8941 B0 E7 BCS P92A ;if found then return
.P943
8943 20 5A A3 JSR R35A ;else raise "File not found" error.
8946 EQUB &D6
8947 EQUS "not found"
8950 EQUB &00
#if defined _DDOS357
.P951
#endif
;*INFO
8951 20 2B 89 JSR P92B ;allow wildcard characters in filename
8954 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
8957 20 35 89 JSR P935 ;ensure file matching spec in catalogue
.P95A
895A 20 C0 89 JSR P9C0 ;print *INFO line
895D 20 6A 89 JSR P96A ;find next matching file
8960 B0 F8 BCS P95A ;loop until no more files match.
8962 60 RTS
.P963 ;Search for file in catalogue
8963 20 92 92 JSR Q292 ;ensure current volume catalogue loaded
8966 A0 F8 LDY #&F8 ;y=&F8, start beyond first catalogue entry
8968 D0 03 BNE P96D ;and jump into search loop (always)
.P96A ;Find next matching file
896A AC CF 10 LDY &10CF ;set Y = catalogue pointer
.P96D
896D 20 72 A4 JSR R472 ;add 8 to Y
8970 CC 05 0F CPY &0F05 ;have we reached the end of the catalogue?
8973 B0 44 BCS P9B9 ;if so return C=0 file not found
8975 20 72 A4 JSR R472 ;else add 8 to Y
8978 A2 07 LDX #&07 ;x=7 point to directory character:
.P97A
897A B5 C7 LDA &C7,X ;get character of current filename
897C CD D0 10 CMP &10D0 ;compare with wildcard mask
897F F0 0E BEQ P98F ;if ='#' and wildcards allowed accept char
8981 20 9A A4 JSR R49A ;else set C=0 iff character in A is a letter
8984 59 07 0E EOR &0E07,Y ;compare with character in catalogue
8987 B0 02 BCS P98B ;if character in current filename is letter
8989 29 DF AND #&DF ;then ignore case
.P98B
898B 29 7F AND #&7F ;ignore bit 7, Z=1 if characters equal
898D D0 09 BNE P998 ;if not equal then test next file
.P98F
898F 88 DEY ;loop to test next (previous) char of name
8990 CA DEX
8991 10 E7 BPL P97A ;if no more chars to test then files match
8993 8C CF 10 STY &10CF ;save cat. offset of found file in workspace
8996 38 SEC ;return C=1 file found
8997 60 RTS
.P998 ;catalogue entry does not match file spec
8998 88 DEY ;advance catalogue pointer to next file
8999 CA DEX
899A 10 FC BPL P998
899C 30 CF BMI P96D ;loop until file found or not
.P99E ;Delete catalogue entry
899E 20 F8 9B JSR QBF8 ;ensure file not locked or open (mutex)
.P9A1
89A1 B9 10 0E LDA &0E10,Y ;copy next file's entry over previous entry
89A4 99 08 0E STA &0E08,Y ;shifting entries up one place
89A7 B9 10 0F LDA &0F10,Y ;(copies title/boot/size if catalogue full)
89AA 99 08 0F STA &0F08,Y
89AD C8 INY ;loop until current file count reached
89AE CC 05 0F CPY &0F05 ;have we reached the end of the catalogue?
89B1 90 EE BCC P9A1
89B3 98 TYA ;copy Y to A = pointer to last file; C=1
89B4 E9 08 SBC #&08 ;subtract 8, catalogue contains one less file
89B6 8D 05 0F STA &0F05 ;store new file count
.P9B9
89B9 18 CLC
.P9BA
89BA 60 RTS
.P9BB ;Print *INFO line if verbose
89BB 2C D1 10 BIT &10D1 ;test *OPT 1 setting
89BE 30 FA BMI P9BA ;if b7=1 then *OPT 1,0 do not print, else:
.P9C0 ;Print *INFO line
89C0 20 00 A3 JSR R300 ;save AXY
89C3 20 A6 88 JSR P8A6 ;print filename from catalogue
89C6 98 TYA ;save catalogue pointer
89C7 48 PHA
89C8 A9 60 LDA #&60 ;set up pointer to OSFILE block in workspace
89CA 85 B0 STA &B0 ;at &1060
89CC A9 10 LDA #&10
89CE 85 B1 STA &B1
89D0 20 06 8A JSR PA06 ;return catalogue information to OSFILE block
89D3 A0 02 LDY #&02
89D5 20 CC A2 JSR R2CC ;print a space
89D8 20 F4 89 JSR P9F4 ;print load address
89DB 20 F4 89 JSR P9F4 ;print execution address
89DE 20 F4 89 JSR P9F4 ;print file length
89E1 68 PLA ;restore catalogue pointer
89E2 A8 TAY
89E3 B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
89E6 29 03 AND #&03 ;extract MSB start sector
89E8 20 31 A4 JSR R431 ;print hex nibble
89EB B9 0F 0F LDA &0F0F,Y ;get LSB start sector
89EE 20 29 A4 JSR R429 ;print hex byte
89F1 4C 67 84 JMP P467 ;print newline
.P9F4
89F4 A2 03 LDX #&03 ;Print 24-bit field at &1060,Y
.P9F6
89F6 B9 62 10 LDA &1062,Y ;get byte at &1062,Y
89F9 20 29 A4 JSR R429 ;print hex byte
89FC 88 DEY ;increment offset
89FD CA DEX ;decrement counter
89FE D0 F6 BNE P9F6 ;loop until 3 bytes printed
8A00 20 73 A4 JSR R473 ;add 7 to Y to point to MSB of next field
8A03 4C CC A2 JMP R2CC ;print a space and exit
.PA06 ;Return catalogue information to OSFILE block
8A06 20 00 A3 JSR R300 ;save AXY
8A09 98 TYA ;save catalogue pointer on stack
8A0A 48 PHA
8A0B AA TAX ;and copy to X
8A0C A0 02 LDY #&02 ;clear bytes at offsets 2..17
8A0E A9 00 LDA #&00
.PA10
8A10 91 B0 STA (&B0),Y
8A12 C8 INY
8A13 C0 12 CPY #&12
8A15 D0 F9 BNE PA10
8A17 A0 02 LDY #&02 ;offset 2 = LSB load address
.PA19
8A19 20 55 8A JSR PA55 ;copy two bytes from catalogue to OSFILE block
8A1C C8 INY ;skip high bytes of OSFILE field
8A1D C8 INY
8A1E C0 0E CPY #&0E ;loop until 3 fields half-filled:
8A20 D0 F7 BNE PA19 ;load address, execution address, file length
8A22 68 PLA ;restore catalogue pointer
8A23 AA TAX
8A24 BD 0F 0E LDA &0E0F,X ;get directory character
8A27 10 06 BPL PA2F ;if b7=1 then file is locked
8A29 A9 0A LDA #&0A ;so set attributes to LR/RW (old style)
8A2B A0 0E LDY #&0E ;no delete, owner read only, public read/write
8A2D 91 B0 STA (&B0),Y ;store in OSFILE block
.PA2F
8A2F BD 0E 0F LDA &0F0E,X ;get top bits exec/length/load/start sector
8A32 A0 04 LDY #&04 ;offset 4 = 2MSB load address
8A34 20 43 8A JSR PA43 ;expand bits 3,2 to top 16 bits of field
8A37 A0 0C LDY #&0C ;offset 12 = 2MSB file length
8A39 4A LSR A ;PA43 returned A = ..eelldd
8A3A 4A LSR A ;shift A right twice to make A = ....eell
8A3B 48 PHA ;save exec address
8A3C 29 03 AND #&03 ;extract bits 1,0 for length (don't expand)
8A3E 91 B0 STA (&B0),Y ;store in OSFILE block
8A40 68 PLA ;restore exec address in bits 3,2
8A41 A0 08 LDY #&08 ;offset 8 = 2MSB execution address:
.PA43
8A43 4A LSR A ;shift A right 2 places
8A44 4A LSR A
8A45 48 PHA ;save shifted value for return
8A46 29 03 AND #&03 ;extract bits 3,2 of A on entry
8A48 C9 03 CMP #&03 ;if either one is clear
8A4A D0 05 BNE PA51 ;then save both as b1,0 of 2MSB
8A4C A9 FF LDA #&FF ;else set MSB and 2MSB = &FF.
8A4E 91 B0 STA (&B0),Y
8A50 C8 INY
.PA51
8A51 91 B0 STA (&B0),Y
8A53 68 PLA ;discard byte on stack
8A54 60 RTS
.PA55
8A55 20 58 8A JSR PA58 ;Copy two bytes from catalogue to OSFILE block
.PA58
8A58 BD 08 0F LDA &0F08,X
8A5B 91 B0 STA (&B0),Y
8A5D E8 INX
8A5E C8 INY
8A5F 60 RTS
;*STAT
8A60 A2 00 LDX #&00 ;x=0, nothing specified
8A62 20 E5 A4 JSR R4E5 ;select specified or default volume
8A65 8A TXA ;test bit 0 of X
8A66 29 01 AND #&01 ;if X=1 drive and volume specified
8A68 F0 03 BEQ PA6D
8A6A 4C A7 8A JMP PAA7 ;then stat specified volume, else:
.PA6D ;*STAT eight volumes if double density
8A6D A5 CF LDA &CF ;get current volume
8A6F 29 0F AND #&0F ;extract drive number
8A71 85 CF STA &CF ;set current volume letter to A
8A73 A9 00 LDA #&00 ;data transfer call &00 = read data
8A75 8D 00 10 STA &1000 ;set data transfer call number
8A78 20 A4 A5 JSR R5A4 ;detect disc format/set sector address
8A7B 2C E3 10 BIT &10E3 ;test density flag
8A7E 70 03 BVS PA83 ;if double density then *STAT eight volumes
8A80 4C A7 8A JMP PAA7 ;else *STAT the single volume
.PA83 ;*STAT eight volumes
8A83 20 00 8C JSR PC00 ;print disc type and volume list
8A86 A2 00 LDX #&00 ;for each volume letter A..H:
.PA88
8A88 BD 06 10 LDA &1006,X ;test if number of tracks in volume > 0
8A8B F0 0D BEQ PA9A ;if = 0 then no such volume, skip
8A8D 8A TXA ;save volume counter
8A8E 48 PHA
8A8F 20 67 84 JSR P467 ;print newline
8A92 20 92 92 JSR Q292 ;ensure current volume catalogue loaded
8A95 20 16 8D JSR PD16 ;print volume statistics
8A98 68 PLA ;restore volume counter
8A99 AA TAX
.PA9A
8A9A 18 CLC
8A9B A5 CF LDA &CF ;get current volume
8A9D 69 10 ADC #&10 ;increment volume letter
8A9F 85 CF STA &CF ;set as current volume
8AA1 E8 INX ;increment counter
8AA2 E0 08 CPX #&08 ;loop until 8 volumes catalogued
8AA4 D0 E2 BNE PA88
8AA6 60 RTS
.PAA7 ;*STAT specified volume
8AA7 20 92 92 JSR Q292 ;ensure current volume catalogue loaded
8AAA 20 00 8C JSR PC00 ;print disc type and volume list
8AAD 4C 16 8D JMP PD16 ;print volume statistics
;*XCAT
8AB0 A2 00 LDX #&00 ;x=0, nothing specified (unused)
8AB2 20 E5 A4 JSR R4E5 ;select specified or default volume
8AB5 A5 CF LDA &CF ;get current volume
8AB7 29 0F AND #&0F ;extract drive number
8AB9 85 CF STA &CF ;set current volume letter to A
8ABB A9 00 LDA #&00 ;data transfer call &00 = read data
8ABD 8D 00 10 STA &1000 ;set data transfer call number
8AC0 20 A4 A5 JSR R5A4 ;detect disc format/set sector address
8AC3 2C E3 10 BIT &10E3 ;test density flag
8AC6 70 03 BVS PACB ;if double density then *CAT eight volumes
8AC8 4C 63 95 JMP Q563 ;else *CAT the single volume
.PACB ;*CAT eight volumes
8ACB 20 00 8C JSR PC00 ;print disc type and volume list
8ACE A2 00 LDX #&00 ;for each volume letter A..H:
.PAD0
8AD0 BD 06 10 LDA &1006,X ;test if number of tracks in volume > 0
8AD3 F0 10 BEQ PAE5 ;if = 0 then no such volume, skip
8AD5 8A TXA ;save volume counter
8AD6 48 PHA
8AD7 20 92 92 JSR Q292 ;ensure current volume catalogue loaded
8ADA 20 D6 8B JSR PBD6 ;print volume title
8ADD 20 7F 8C JSR PC7F ;print volume spec and boot option
8AE0 20 02 8B JSR PB02 ;list files in catalogue
8AE3 68 PLA ;restore volume counter
8AE4 AA TAX
.PAE5
8AE5 18 CLC
8AE6 A5 CF LDA &CF ;get current volume
8AE8 69 10 ADC #&10 ;select next volume letter
8AEA 85 CF STA &CF ;set as current volume
8AEC E8 INX ;increment counter
8AED E0 08 CPX #&08 ;have 8 volumes A..H been listed?
8AEF D0 DF BNE PAD0 ;if not then loop
8AF1 60 RTS
.PAF2
8AF2 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
8AF5 EQUB &0D ;newline
8AF6 EQUB &0A
8AF7 EQUS "No file"
8AFE EQUB &0D ;newline
8AFF EQUB &0A
8B00 EQUB &FF
8B01 60 RTS
.PB02 ;List files in catalogue
8B02 AD 05 0F LDA &0F05 ;get number of files in catalogue * 8
8B05 F0 EB BEQ PAF2 ;if catalogue empty then print "No file"
8B07 A0 FF LDY #&FF
8B09 84 A8 STY &A8
8B0B C8 INY
8B0C 84 AA STY &AA
.PB0E
8B0E CC 05 0F CPY &0F05 ;have we reached the end of the catalogue?
8B11 B0 17 BCS PB2A ;if so then start sorting entries
8B13 B9 0F 0E LDA &0E0F,Y ;else get directory character of cat entry
8B16 4D CA 10 EOR &10CA ;compare with default (CSD) directory
8B19 29 7F AND #&7F ;mask off lock bit
8B1B D0 08 BNE PB25 ;if directories differ skip to next entry
8B1D B9 0F 0E LDA &0E0F,Y ;else set directory character to NUL
8B20 29 80 AND #&80 ;and preserve lock bit
8B22 99 0F 0E STA &0E0F,Y
.PB25
8B25 20 72 A4 JSR R472 ;add 8 to Y
8B28 90 E4 BCC PB0E ;and loop (always)
.PB2A
8B2A A0 00 LDY #&00 ;Y=&00, start at first file entry
8B2C 20 AA 8B JSR PBAA ;find unlisted catalogue entry
8B2F B0 6E BCS PB9F ;if none remaining then finish catalogue
.PB31
8B31 84 AB STY &AB ;save catalogue pointer
8B33 A2 00 LDX #&00 ;set filename offset = 0
.PB35
8B35 B9 08 0E LDA &0E08,Y ;copy name and directory of first entry
8B38 29 7F AND #&7F ;with b7 clear
8B3A 9D 60 10 STA &1060,X ;to workspace
8B3D C8 INY
8B3E E8 INX
8B3F E0 08 CPX #&08 ;loop until 8 characters copied
8B41 D0 F2 BNE PB35
.PB43
8B43 20 AA 8B JSR PBAA ;find unlisted catalogue entry
8B46 B0 1F BCS PB67 ;if none remaining then print lowest entry
8B48 38 SEC ;else set C=1 for subtraction
8B49 A2 06 LDX #&06 ;start at 6th character (LSB) of leaf name:
.PB4B
8B4B B9 0E 0E LDA &0E0E,Y ;get character of entry
8B4E FD 60 10 SBC &1060,X ;subtract character of workspace
8B51 88 DEY ;loop until 7 characters compared
8B52 CA DEX
8B53 10 F6 BPL PB4B
8B55 20 73 A4 JSR R473 ;add 7 to Y
8B58 B9 0F 0E LDA &0E0F,Y ;get directory character (MSB) of entry
8B5B 29 7F AND #&7F ;mask off lock bit
8B5D ED 67 10 SBC &1067 ;subtract directory character in workspace
8B60 90 CF BCC PB31 ;if entry < wksp then copy entry to wksp
8B62 20 72 A4 JSR R472 ;else add 8 to Y
8B65 B0 DC BCS PB43 ;and loop (always)
.PB67
8B67 A4 AB LDY &AB ;get catalogue pointer
8B69 B9 08 0E LDA &0E08,Y ;set b7 in first character of leaf name
8B6C 09 80 ORA #&80 ;marking entry as listed
8B6E 99 08 0E STA &0E08,Y
8B71 AD 67 10 LDA &1067 ;get directory character from workspace
8B74 C5 AA CMP &AA ;compare with last one printed
8B76 F0 10 BEQ PB88 ;if same then add entry to group
8B78 A6 AA LDX &AA ;else test previous directory
8B7A 85 AA STA &AA ;set previous directory = current directory
8B7C D0 0A BNE PB88 ;if prev=NUL we go from CSD to other dirs
8B7E 20 67 84 JSR P467 ;so print double newline:
.PB81
8B81 20 67 84 JSR P467 ;print newline
8B84 A0 FF LDY #&FF ;set Y = &FF going to 0, start of line
8B86 D0 09 BNE PB91 ;branch (always)
.PB88
8B88 A4 A8 LDY &A8 ;have we printed two entries on this line?
8B8A D0 F5 BNE PB81 ;if so then print newline and reset counter
8B8C A0 05 LDY #&05 ;else tab to next field. Y = 5 spaces
8B8E 20 DA 88 JSR P8DA ;print number of spaces in Y
.PB91
8B91 C8 INY
8B92 84 A8 STY &A8 ;y = index of next entry on this line
8B94 A4 AB LDY &AB ;get catalogue pointer
8B96 20 C9 A2 JSR R2C9 ;print two spaces
8B99 20 A6 88 JSR P8A6 ;print filename from catalogue
8B9C 4C 2A 8B JMP PB2A ;loop until all files listed
.PB9F
8B9F A9 FF LDA #&FF
8BA1 8D 84 10 STA &1084 ;forget catalogue in pages &0E..F
8BA4 4C 67 84 JMP P467 ;print newline
.PBA7 ;Find next unlisted catalogue entry
8BA7 20 72 A4 JSR R472 ;add 8 to Y
.PBAA ;Find unlisted catalogue entry
8BAA CC 05 0F CPY &0F05 ;if catalogue pointer beyond last file
8BAD B0 05 BCS PBB4 ;then return C=1
8BAF B9 08 0E LDA &0E08,Y ;else test first character of leaf name
8BB2 30 F3 BMI PBA7 ;if b7=1 then already listed, skip
.PBB4
8BB4 60 RTS ;else return C=0, catalogue pointer in Y
.PBB5 ;Print volume spec in A (assuming DD)
8BB5 2C B4 8B BIT &8BB4 ;set V=1
8BB8 70 03 BVS PBBD ;always print volume letter B..H after drive
.PBBA ;Print volume spec in A
8BBA 2C E3 10 BIT &10E3 ;test density flag
.PBBD
8BBD 08 PHP ;save density flag on stack
8BBE 48 PHA ;save volume on stack
8BBF 29 07 AND #&07 ;extract bits 2..0, drive 0..7
8BC1 20 31 A4 JSR R431 ;print hex nibble
8BC4 68 PLA ;restore volume
8BC5 28 PLP ;restore density flag
8BC6 50 06 BVC PBCE ;if single density then only print drive no.
8BC8 4A LSR A ;else shift volume letter to bits 2..0
8BC9 4A LSR A
8BCA 4A LSR A
8BCB 4A LSR A
8BCC D0 01 BNE PBCF ;if volume letter is not A then print it
.PBCE
8BCE 60 RTS ;else exit
.PBCF
8BCF 88 DEY ;decrement Y (no. spaces to print later)
8BD0 18 CLC ;add ASCII value of "A"
8BD1 69 41 ADC #&41 ;to produce volume letter B..H
8BD3 4C 03 A4 JMP R403 ;print character in A (OSASCI) and exit
.PBD6 ;Print volume title
8BD6 A0 0B LDY #&0B ;set y = &0B print 11 spaces
8BD8 20 DA 88 JSR P8DA ;print number of spaces in Y
.PBDB
8BDB B9 00 0E LDA &0E00,Y ;y=0; if Y=0..7 get char from sector 0
8BDE C0 08 CPY #&08 ;if Y=8..11
8BE0 90 03 BCC PBE5
8BE2 B9 F8 0E LDA &0EF8,Y ;then get character of title from sector 1
.PBE5
8BE5 20 03 A4 JSR R403 ;print character in A (OSASCI)
8BE8 C8 INY ;loop until 12 characters of title printed
8BE9 C0 0C CPY #&0C
8BEB D0 EE BNE PBDB
8BED 20 94 A3 JSR R394 ;print " ("
8BF0 EQUB &0D
8BF1 EQUS " ("
8BF3 AD 04 0F LDA &0F04 ;get BCD catalogue cycle number
8BF6 20 29 A4 JSR R429 ;print hex byte
8BF9 20 94 A3 JSR R394 ;print ")" +newline
8BFC EQUS ")"
8BFD EQUB &0D
8BFE EA NOP
8BFF 60 RTS
.PC00 ;Print disc type and volume list
8C00 A9 83 LDA #&83 ;teletext char &83 = yellow alphanumerics
8C02 20 03 A4 JSR R403 ;print character in A (OSASCI)
8C05 A5 CF LDA &CF ;get current volume
8C07 29 0C AND #&0C ;extract bits 2,3 of drive number
8C09 D0 65 BNE PC70 ;if drive number more than 3 print "RAM Disk"
8C0B 2C E3 10 BIT &10E3 ;else test density flag
8C0E 70 09 BVS PC19 ;if double density print "Double density"
8C10 20 94 A3 JSR R394 ;else print "Single density"
8C13 EQUS "Sing"
8C17 90 08 BCC PC21
.PC19
8C19 20 94 A3 JSR R394
8C1C EQUS "Doub"
8C20 EA NOP
.PC21
8C21 20 94 A3 JSR R394
8C24 EQUS "le density"
8C2E EA NOP
8C2F A9 87 LDA #&87 ;teletext char &87 = white alphanumerics
8C31 20 03 A4 JSR R403 ;print character in A (OSASCI)
8C34 A0 0E LDY #&0E ;set Y = 14 spaces for single density
8C36 2C E3 10 BIT &10E3 ;test density flag
8C39 50 1E BVC PC59 ;if single density skip list of volumes
8C3B A0 05 LDY #&05 ;else Y = 5 spaces for double density
8C3D 20 DA 88 JSR P8DA ;print number of spaces in Y
8C40 A2 00 LDX #&00 ;set volume index = 0, start at volume A:
.PC42
8C42 18 CLC ;clear carry for add
8C43 BD 06 10 LDA &1006,X ;test if number of tracks in volume > 0
8C46 08 PHP ;preserve result
8C47 8A TXA ;copy index to A to make volume letter
8C48 28 PLP ;restore result
8C49 D0 02 BNE PC4D ;if volume present print its letter
8C4B A9 ED LDA #&ED ;else A=&ED + &41 = &2E, ".":
.PC4D
8C4D 69 41 ADC #&41 ;add ASCII value of "A"
8C4F 20 03 A4 JSR R403 ;print character in A (OSASCI)
8C52 E8 INX ;point to next volume
8C53 E0 08 CPX #&08 ;have all 8 volumes been listed?
8C55 D0 EB BNE PC42 ;if not then loop
8C57 A0 01 LDY #&01 ;else Y=1 space separating volume list:
.PC59
8C59 2C E0 10 BIT &10E0 ;test double-stepping flag
8C5C 10 0F BPL PC6D ;if set manually (*4080 ON/OFF) then end line
8C5E 50 0D BVC PC6D ;if 1:1 stepping was detected then end line
8C60 20 DA 88 JSR P8DA ;else print 1 or 14 spaces
8C63 20 94 A3 JSR R394 ;print "40in80"
8C66 EQUS "40in80"
8C6C EA NOP
.PC6D
8C6D 4C 67 84 JMP P467 ;print newline
.PC70
8C70 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
8C73 EQUS "RAM Disk"
8C7B EQUB &FF
8C7C 4C 67 84 JMP P467 ;print newline
.PC7F ;Print volume spec and boot option
8C7F A0 0D LDY #&0D ;set Y = &0D print 13 spaces
8C81 A5 CF LDA &CF ;get current volume
8C83 20 08 8D JSR PD08 ;print " Drive " plus volume spec in A
8C86 20 DA 88 JSR P8DA ;print number of spaces in Y
8C89 20 94 A3 JSR R394 ;print "Option "
8C8C EQUS "Option "
8C93 AD 06 0F LDA &0F06 ;get boot option/top bits volume size
8C96 20 67 A4 JSR R467 ;shift A right 4 places
8C99 20 31 A4 JSR R431
8C9C 20 94 A3 JSR R394 ;print " ("
8C9F EQUS " ("
8CA1 A0 03 LDY #&03 ;4 characters to print
8CA3 0A ASL A ;multiply boot option by 4
8CA4 0A ASL A
8CA5 AA TAX ;transfer to X for use as offset
.PCA6
8CA6 BD F8 8C LDA &8CF8,X ;get character of boot option descriptor
8CA9 20 03 A4 JSR R403 ;print character in A (OSASCI)
8CAC E8 INX ;increment offset
8CAD 88 DEY ;decrement count
8CAE 10 F6 BPL PCA6 ;loop until 4 characters printed
8CB0 20 94 A3 JSR R394 ;print ")" + newline
8CB3 EQUS ")"
8CB4 EQUB &0D
8CB5 EA NOP
8CB6 60 RTS
.PCB7 ;Print CSD and library directories
8CB7 20 94 A3 JSR R394 ;print "Directory :"
8CBA EQUS " Directory :"
8CC6 A0 06 LDY #&06 ;6 characters in next field
8CC8 AD CB 10 LDA &10CB ;get default volume
8CCB 20 B5 8B JSR PBB5 ;print volume spec in A (assuming DD)
8CCE 20 01 A4 JSR R401 ;print a dot
8CD1 AD CA 10 LDA &10CA ;get default directory
8CD4 20 03 A4 JSR R403 ;print character in A (OSASCI)
8CD7 20 DA 88 JSR P8DA ;print number of spaces in Y
8CDA 20 94 A3 JSR R394 ;print "Library :"
8CDD EQUS "Library :"
8CE6 AD CD 10 LDA &10CD ;get library volume
8CE9 20 B5 8B JSR PBB5 ;print volume spec in A (assuming DD)
8CEC 20 01 A4 JSR R401 ;print a dot
8CEF AD CC 10 LDA &10CC
8CF2 20 03 A4 JSR R403 ;print character in A (OSASCI)
8CF5 4C 67 84 JMP P467 ;print newline
;Table of boot option descriptors 0..3
8CF8 EQUS "off"
8CFB EQUB &00
8CFC EQUS "LOAD"
8D00 EQUS "RUN"
8D03 EQUB &00
8D04 EQUS "EXEC"
.PD08 ;Print " Drive " plus volume spec in A
8D08 20 94 A3 JSR R394
8D0B EQUS " Drive "
8D12 EA NOP
8D13 4C BA 8B JMP PBBA ;print volume spec in A
.PD16 ;Print volume statistics
8D16 A0 03 LDY #&03 ;y=3 print 2 spaces/ 1 space
8D18 A5 CF LDA &CF ;get current volume
8D1A 20 08 8D JSR PD08 ;print " Drive " plus volume spec in A
8D1D 20 DA 88 JSR P8DA ;print number of spaces in Y
8D20 20 94 A3 JSR R394
8D23 EQUS "Volume size "
8D31 EA NOP
8D32 AD 07 0F LDA &0F07 ;copy volume size to sector count
8D35 85 B0 STA &B0 ;LSB
8D37 AD 06 0F LDA &0F06 ;get boot option/top bits volume size
8D3A 29 03 AND #&03 ;mask top bits volume size
8D3C 85 B1 STA &B1 ;store MSB
8D3E 20 72 8D JSR PD72 ;print sector count as kilobytes
8D41 20 7B 8D JSR PD7B ;print "K"
8D44 20 67 84 JSR P467 ;print newline
8D47 A0 0B LDY #&0B ;set Y = &0B print 11 spaces
8D49 20 DA 88 JSR P8DA ;print number of spaces in Y
8D4C 20 94 A3 JSR R394 ;print "Volume unused"
8D4F EQUS "Volume unused "
8D5D EA NOP
8D5E 20 EA A1 JSR R1EA ;calculate free space on volume
8D61 A5 C0 LDA &C0 ;copy result to sector count
8D63 85 B0 STA &B0
8D65 A5 C1 LDA &C1
8D67 85 B1 STA &B1
8D69 20 72 8D JSR PD72 ;print sector count as kilobytes
8D6C 20 7B 8D JSR PD7B ;print "K"
8D6F 4C 67 84 JMP P467 ;print newline
.PD72 ;Print sector count as kilobytes
8D72 20 81 8D JSR PD81 ;divide sector count by 4
8D75 20 5D AE JSR RE5D ;convert binary word to four decimal digits
8D78 4C 66 B0 JMP S066 ;print four decimal digits, space-padded
.PD7B ;Print "K"
8D7B 20 94 A3 JSR R394
8D7E EQUS "K"
8D7F EA NOP
8D80 60 RTS
.PD81 ;Divide word by 4
8D81 46 B1 LSR &B1
8D83 66 B0 ROR &B0
8D85 46 B1 LSR &B1
8D87 66 B0 ROR &B0
8D89 60 RTS
;DFS command table
8D8A EQUS "4080"
8D8E EQUW &B4,&01
8D90 EQUB &8D ;syntax &D: b7=1
8D91 EQUS "ACCESS"
8D97 EQUW &90,&A5
8D99 EQUB &32 ;syntax &2,&3: (L)
8D9A EQUS "BACKUP"
8DA0 EQUW &85,&3B
8DA2 EQUB &54 ;syntax &4,&5:
8DA3 EQUS "COMPACT"
8DAA EQUW &A0,&F4
8DAC EQUB &0A ;syntax &A: ()
8DAD EQUS "COPY"
8DB1 EQUW &86,&3E
8DB3 EQUB &64 ;syntax &4,&6:
8DB4 EQUS "DELETE"
8DBA EQUW &8F,&7B
8DBC EQUB &01 ;syntax &1:
8DBD EQUS "DENSITY"
8DC4 EQUW &B3,&D7
8DC6 EQUB &8D ;syntax &D: b7=1
8DC7 EQUS "DESTROY"
8DCE EQUW &8F,&8A
8DD0 EQUB &02 ;syntax &2:
8DD1 EQUS "DIR"
8DD4 EQUW &90,&37
8DD6 EQUB &09 ;syntax &9: ()
8DD7 EQUS "DRIVE"
8DDC EQUW &90,&2E
8DDE EQUB &0A ;syntax &A: ()
8DDF EQUS "ENABLE"
8DE5 EQUW &92,&13
8DE7 EQUB &00 ;syntax &0: no arguments
8DE8 EQUS "INFO"
8DEC EQUW &89,&51
8DEE EQUB &02 ;syntax &2:
8DEF EQUS "LIB"
8DF2 EQUW &90,&3A
8DF4 EQUB &09 ;syntax &9: ()
8DF5 EQUS "MCOPY"
8DFA EQUW &9E,&2D
8DFC EQUB &D4 ;syntax &4,&5: b7=1
8DFD EQUS "RENAME"
8E03 EQUW &92,&4C
8E05 EQUB &78 ;syntax &8,&7:
8E06 EQUS "SROM"
8E0A EQUW &90,&5D
8E0C EQUB &8C ;syntax &C: b7=1
8E0D EQUS "STAT"
8E11 EQUW &8A,&60
8E13 EQUB &0A ;syntax &A: ()
8E14 EQUS "TAPEDISK"
8E1C EQUW &93,&6C
8E1E EQUB &81 ;syntax &1: b7=1
8E1F EQUS "TITLE"
8E24 EQUW &90,&76
8E26 EQUB &0B ;syntax &B:
8E27 EQUS "WIPE"
8E2B EQUW &8F,&49
8E2D EQUB &02 ;syntax &2:
8E2E EQUS "XCAT"
8E32 EQUW &8A,&B0
8E34 EQUB &0A ;syntax &A: ()
;DDOSX command table
8E35 EQUS "COPYRIGHT"
#if defined _DDOS316
8E3E EQUW &BE,&33
#elif defined _DDOS336
8E3E EQUW &BE,&21
#elif defined _DDOS346
8E3E EQUW &BE,&43
#else
8E3E EQUW &BE,&42
#endif
8E40 EQUB &80 ;syntax &0: no arguments b7=1
8E41 EQUS "FDCSTAT"
8E48 EQUW &B5,&66
8E4A EQUB &80 ;syntax &0: no arguments b7=1
8E4B EQUS "RAMINIT"
8E52 EQUW &B4,&31
8E54 EQUB &80 ;syntax &0: no arguments b7=1
8E55 EQUS "ROMID"
8E5A EQUW &94,&2A
8E5C EQUB &80 ;syntax &0: no arguments b7=1
8E5D EQUW &94,&D1 ;unrecognised command, *RUN it &94D1
;Utility command table
8E5F EQUS "BUILD"
8E64 EQUW &84,&17
8E66 EQUB &01 ;syntax &1:
8E67 EQUS "DISC"
8E6B EQUW &82,&0F
8E6D EQUB &00 ;syntax &0: no arguments
8E6E EQUS "DUMP"
8E72 EQUW &83,&9F
8E74 EQUB &01 ;syntax &1:
8E75 EQUS "FORMAT"
8E7B EQUW &A8,&A1
8E7D EQUB &8D ;syntax &D: b7=1
8E7E EQUS "LIST"
8E82 EQUW &83,&5D
8E84 EQUB &01 ;syntax &1:
8E85 EQUS "TYPE"
8E89 EQUW &83,&56
8E8B EQUB &01 ;syntax &1:
8E8C EQUS "VERIFY"
8E92 EQUW &AA,&55
8E94 EQUB &8A ;syntax &A: () b7=1
8E95 EQUS "VOLGEN"
8E9B EQUW &AB,&47
8E9D EQUB &8A ;syntax &A: () b7=1
;entry not printed in *HELP UTILS
8E9E EQUS "DISK"
8EA2 EQUW &82,&0F
8EA4 EQUB &00 ;syntax &0: no arguments
8EA5 EQUW &8E,&C6 ;unrecognised utility, return &8EC6
;*HELP keyword table
8EA7 EQUS "DDOS"
8EAB EQUW &9F,&E8
8EAD EQUB &00
8EAE EQUS "DFS"
8EB1 EQUW &9F,&E8
8EB3 EQUB &00
8EB4 EQUS "UTILS"
8EB9 EQUW &9F,&E0
8EBB EQUB &00
8EBC EQUS "DDOSX"
8EC1 EQUW &9F,&F0
8EC3 EQUB &00
8EC4 EQUW &8E,&C6 ;unrecognised keyword, return &8EC6
8EC6 60 RTS
;on entry A=string offset (=Y to GSINIT)
;XY=address of table
.PEC7 ;Search for command or keyword in table
8EC7 20 28 8F JSR PF28 ;set up trampoline to read table at XY
8ECA 48 PHA ;save string offset
.PECB
8ECB 68 PLA ;restore offset of start of command line
8ECC A8 TAY
8ECD 48 PHA
8ECE 20 BB A4 JSR R4BB ;call GSINIT with C=0
8ED1 A2 00 LDX #&00 ;start at current trampoline address
8ED3 20 AA 00 JSR &00AA ;fetch first byte
8ED6 38 SEC ;if terminator,empty keyword matches anything
8ED7 30 3B BMI PF14 ;so jump to following action address with C=1
8ED9 CA DEX ;else decrement X and Y to stay in place:
8EDA 88 DEY
.PEDB
8EDB E8 INX ;advance command line and table offsets
8EDC C8 INY
8EDD 20 AA 00 JSR &00AA ;get byte from table
8EE0 30 22 BMI PF04 ;if terminator, check command also terminates
8EE2 51 F2 EOR (&F2),Y ;else compare with character of command
8EE4 29 5F AND #&5F ;make comparison case-insensitive
8EE6 F0 F3 BEQ PEDB ;if equal then compare next characters
8EE8 B1 F2 LDA (&F2),Y ;else get mismatching character of command
8EEA C9 2E CMP #&2E ;is it a dot?
8EEC 08 PHP ;save the result
.PEED
8EED E8 INX ;scan keyword in table
8EEE 20 AA 00 JSR &00AA
8EF1 10 FA BPL PEED ;loop until terminator reached
8EF3 E8 INX ;skip action address, 2 bytes
8EF4 E8 INX
8EF5 28 PLP ;is the command an abbreviation or a mismatch?
8EF6 D0 05 BNE PEFD ;if mismatch then skip syntax, scan next kywd
8EF8 20 AA 00 JSR &00AA ;else test syntax byte
8EFB 10 13 BPL PF10 ;if b7=0 accept cmd, else abbrev. not allowed:
.PEFD
8EFD E8 INX ;skip syntax byte
8EFE 20 37 8F JSR PF37 ;add X to trampoline address
8F01 4C CB 8E JMP PECB ;scan next keyword
.PF04
8F04 B1 F2 LDA (&F2),Y ;get character of command
8F06 20 9A A4 JSR R49A ;set C=0 iff character in A is a letter
8F09 B0 08 BCS PF13 ;if C=1 accept command, else longer than kywd
8F0B E8 INX ;so skip action address, 2 bytes
8F0C E8 INX
8F0D 4C FD 8E JMP PEFD ;skip syntax byte and scan next keyword
.PF10 ;Accept abbreviated command
8F10 CA DEX ;backtrack to action address, 2 bytes
8F11 CA DEX
8F12 C8 INY ;advance command line offset past the dot:
.PF13 ;Accept command
8F13 18 CLC ;set C=0 command valid
.PF14
8F14 68 PLA ;discard offset to start of command
8F15 20 AA 00 JSR &00AA ;get action address high byte
8F18 85 A9 STA &A9 ;store high byte of vector
8F1A E8 INX ;advance to next byte of table
8F1B 20 AA 00 JSR &00AA ;get action address low byte
8F1E 85 A8 STA &A8 ;store low byte of vector
8F20 E8 INX ;return X=offset of syntax byte
8F21 60 RTS ;y=offset of command line tail.
#if defined _DDOS357
.PF24
8F24 A2 E8 LDX #&E8 ;point XY to *INFO command table entry
8F26 A0 8D LDY #&8D ;fall through:
#else
;unreachable code
8F22 48 PHA ;set up trampoline to write table at XY
8F23 A9 9D LDA #&9D
8F25 4C 2B 8F JMP PF2B
#endif
.PF28 ;Set up trampoline to read table at XY
8F28 48 PHA
8F29 A9 BD LDA #&BD ;&BD = LDA abs,X
.PF2B
8F2B 85 AA STA &AA ;instruction at &00AA = LDA xy,X
8F2D 86 AB STX &AB
8F2F 84 AC STY &AC
8F31 A9 60 LDA #&60 ;instruction at &00AD = RTS
8F33 85 AD STA &AD
8F35 68 PLA ;restore A
8F36 60 RTS
.PF37 ;Add X to trampoline address
8F37 18 CLC
8F38 8A TXA
8F39 65 AB ADC &AB ;add X to low byte of LDA,X address
8F3B 85 AB STA &AB
8F3D 90 02 BCC PF41 ;carry out to high byte
8F3F E6 AC INC &AC
.PF41
8F41 60 RTS
.PF42 ;Set GSINIT pointer to XY, set Y=0
8F42 86 F2 STX &F2
8F44 84 F3 STY &F3
8F46 A0 00 LDY #&00
8F48 60 RTS
;*WIPE
8F49 20 E1 8F JSR PFE1 ;ensure file matching wildcard argument
.PF4C
8F4C 20 A6 88 JSR P8A6 ;print filename from catalogue
8F4F 20 94 A3 JSR R394
8F52 EQUS " : "
8F55 EA NOP
8F56 B9 0F 0E LDA &0E0F,Y ;test lock bit
8F59 10 06 BPL PF61 ;if unlocked then ask to delete
8F5B 20 FD A3 JSR R3FD ;else deletion not allowed, print letter N
8F5E 4C 72 8F JMP PF72 ;find next matching file
.PF61
8F61 20 D9 84 JSR P4D9 ;ask user yes or no
8F64 D0 0C BNE PF72 ;if user replies no then find next match
8F66 20 87 88 JSR P887 ;else ensure disc not changed
8F69 20 9E 89 JSR P99E ;delete catalogue entry
8F6C 20 81 92 JSR Q281 ;write volume catalogue
8F6F 20 FF 8F JSR PFFF ;shift cat pointer to follow shifted files
.PF72
8F72 20 67 84 JSR P467 ;print newline
8F75 20 6A 89 JSR P96A ;find next matching file
8F78 B0 D2 BCS PF4C ;if found then wipe the file
8F7A 60 RTS ;else exit
;*DELETE
8F7B 20 2F 89 JSR P92F ;disallow wildcard characters in filename
8F7E 20 E4 8F JSR PFE4 ;ensure file matching argument
8F81 20 BB 89 JSR P9BB ;print *INFO line if verbose
8F84 20 9E 89 JSR P99E ;delete catalogue entry
8F87 4C 81 92 JMP Q281 ;write volume catalogue
;Note: *DESTROY deletes all matching files, locked or unlocked.
;*DESTROY
8F8A 20 3A A2 JSR R23A ;ensure *ENABLE active
8F8D 20 E1 8F JSR PFE1 ;ensure file matching wildcard argument
.PF90
8F90 20 A6 88 JSR P8A6 ;print filename from catalogue
8F93 20 67 84 JSR P467 ;print newline
8F96 20 6A 89 JSR P96A ;find next matching file
8F99 B0 F5 BCS PF90
8F9B 20 94 A3 JSR R394
8F9E EQUB &0D
8F9F EQUS "Delete (Y/N) ? "
8FAE EA NOP
8FAF 20 D9 84 JSR P4D9 ;ask user yes or no
8FB2 F0 03 BEQ PFB7 ;if user replies yes then proceed
8FB4 4C 67 84 JMP P467 ;else print newline and exit
.PFB7
8FB7 20 87 88 JSR P887 ;ensure disc not changed
8FBA 20 63 89 JSR P963 ;search for file in catalogue
.PFBD
8FBD B9 0F 0E LDA &0E0F,Y ;unlock catalogue entry!
8FC0 29 7F AND #&7F
8FC2 99 0F 0E STA &0E0F,Y
8FC5 20 9E 89 JSR P99E ;delete catalogue entry
8FC8 20 FF 8F JSR PFFF
8FCB 20 6A 89 JSR P96A ;find next matching file
8FCE B0 ED BCS PFBD
8FD0 20 81 92 JSR Q281 ;write volume catalogue
8FD3 20 94 A3 JSR R394 ;print "Deleted" and exit
8FD6 EQUB &0D
8FD7 EQUS "Deleted"
8FDE EQUB &0D
8FDF EA NOP
8FE0 60 RTS
.PFE1 ;Ensure file matching wildcard argument
8FE1 20 2B 89 JSR P92B ;allow wildcard characters in filename
.PFE4 ;Ensure file matching argument
8FE4 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
8FE7 4C 35 89 JMP P935 ;ensure file matching spec in catalogue
.PFEA ;Set current file from argument
8FEA 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
8FED 4C E5 87 JMP P7E5 ;set current file from file spec
.PFF0 ;Pack b17,16 of length into catalogue entry
8FF0 20 6D A4 JSR R46D ;shift A left 4 places
8FF3 5D 0E 0F EOR &0F0E,X ;replace b5,b4 of top bits with b5,b4 from A
8FF6 29 30 AND #&30
8FF8 5D 0E 0F EOR &0F0E,X
8FFB 9D 0E 0F STA &0F0E,X ;store top bits back in catalogue
8FFE 60 RTS
.PFFF ;Subtract 8 from catalogue pointer
8FFF AC CF 10 LDY &10CF ;get catalogue pointer
9002 20 7B A4 JSR R47B ;subtract 8 from Y
9005 8C CF 10 STY &10CF ;store catalogue pointer
9008 60 RTS
.Q009 ;Write ordinary file L5
9009 20 59 93 JSR Q359 ;prepare to write from user memory
900C 4C 12 90 JMP Q012 ;transfer ordinary file L5
.Q00F ;Read ordinary file L5
900F 20 50 93 JSR Q350 ;prepare to read to user memory
.Q012 ;Transfer ordinary file L5
9012 20 EA 88 JSR P8EA ;prepare ordinary file transfer
9015 A9 01 LDA #&01 ;a=&01, unused
9017 20 02 A7 JSR R702 ;transfer data and report errors L4
901A 4C 38 93 JMP Q338 ;release Tube and exit
;called only from &877E
.Q01D ;Read extended file L5
901D 20 50 93 JSR Q350 ;prepare to read to user memory
9020 4C 26 90 JMP Q026 ;transfer extended file L5
;called only from &87A2
.Q023 ;Write extended file L5
9023 20 59 93 JSR Q359 ;prepare to write from user memory
.Q026 ;Transfer extended file L5
9026 20 E1 88 JSR P8E1 ;prepare extended file transfer
9029 A9 01 LDA #&01 ;a=&01, unused
902B 4C 02 A7 JMP R702 ;transfer data and report errors L4
;*DRIVE
902E 20 E5 A4 JSR R4E5 ;select specified or default volume
9031 A5 CF LDA &CF ;get current volume
9033 8D CB 10 STA &10CB ;set as default volume
9036 60 RTS
;*DIR
9037 A2 00 LDX #&00
9039 AD A2 02 LDA &02A2 ;*LIB 903A=LDX #&02
903C BD CA 10 LDA &10CA,X ;get default/library directory
903F 85 CE STA &CE ;set as current directory
9041 BD CB 10 LDA &10CB,X ;get default/library volume
9044 85 CF STA &CF ;set as current volume
9046 8A TXA ;save offset
9047 48 PHA
9048 20 BB A4 JSR R4BB ;call GSINIT with C=0
904B F0 03 BEQ Q050
904D 20 1B A5 JSR R51B ;parse directory spec
.Q050
9050 68 PLA ;restore offset
9051 AA TAX
9052 A5 CE LDA &CE ;get current directory
9054 9D CA 10 STA &10CA,X ;set as default/library directory
9057 A5 CF LDA &CF ;get current volume
9059 9D CB 10 STA &10CB,X ;set as default/library volume
905C 60 RTS
;*SROM
905D 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
9060 20 C5 FF JSR &FFC5 ;call GSREAD, get first argument character
9063 20 A0 A4 JSR R4A0 ;convert ASCII hex digit to binary
9066 B0 0B BCS Q073 ;if invalid then raise "Bad command" error
9068 48 PHA ;else save digit
9069 20 C5 FF JSR &FFC5 ;call GSREAD; if more characters in argument
906C 90 05 BCC Q073 ;then raise "Bad command" error
906E 68 PLA ;else get back digit
906F 8D 01 10 STA &1001 ;set *SROM slot number and exit.
9072 60 RTS
.Q073
9073 4C F8 94 JMP Q4F8 ;raise "Bad command" error
;*TITLE
9076 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
9079 20 FB A4 JSR R4FB ;set current vol/dir = default, set up drive
907C 20 9E 92 JSR Q29E ;load volume catalogue L4
907F A2 0B LDX #&0B ;first offset to store = 11
9081 A9 00 LDA #&00 ;set title to 12 NULs:
.Q083
9083 20 99 90 JSR Q099 ;store character of title
9086 CA DEX ;loop until 12 characters stored
9087 10 FA BPL Q083
.Q089
9089 E8 INX ;x=&FF, set X=0 offset of first character
908A 20 C5 FF JSR &FFC5 ;call GSREAD
908D B0 07 BCS Q096 ;if end of argument write catalogue
908F 20 99 90 JSR Q099 ;else store character of title
9092 E0 0B CPX #&0B ;is this the twelfth character written?
9094 90 F3 BCC Q089 ;if not then loop to write more, else:
.Q096
9096 4C 81 92 JMP Q281 ;write volume catalogue and exit
.Q099 ;Store character of title
9099 E0 08 CPX #&08 ;if offset is 8 or more
909B 90 04 BCC Q0A1
909D 9D F8 0E STA &0EF8,X ;then store at &0F00..3, X=8..11
90A0 60 RTS
.Q0A1
90A1 9D 00 0E STA &0E00,X ;else store at &0E00..7, X=0..7
90A4 60 RTS
;*ACCESS
90A5 20 2B 89 JSR P92B ;allow wildcard characters in filename
90A8 20 EA 8F JSR PFEA ;set current file from argument
90AB A2 00 LDX #&00
90AD 20 BB A4 JSR R4BB ;call GSINIT with C=0
90B0 D0 1E BNE Q0D0 ;if argument is empty
.Q0B2
90B2 86 AA STX &AA ;then attribute mask = &00, file unlocked
90B4 20 3E 89 JSR P93E ;ensure matching file in catalogue
.Q0B7
90B7 20 FB 9B JSR QBFB ;ensure file not open (mutex)
90BA B9 0F 0E LDA &0E0F,Y ;get directory character from catalogue
90BD 29 7F AND #&7F ;mask off old attribute
90BF 05 AA ORA &AA ;apply new attribute
90C1 99 0F 0E STA &0E0F,Y ;put back in catalogue
90C4 20 BB 89 JSR P9BB ;print *INFO line if verbose
90C7 20 6A 89 JSR P96A ;find next matching file
90CA B0 EB BCS Q0B7 ;if found then set its attribute
90CC 90 C8 BCC Q096 ;else write volume catalogue and exit
.Q0CE
90CE A2 80 LDX #&80 ;found L, set bit 7 to indicate file locked:
.Q0D0
90D0 20 C5 FF JSR &FFC5 ;call GSREAD, get character of attribute
90D3 B0 DD BCS Q0B2 ;if end of string then set attribute
90D5 C9 4C CMP #&4C ;else is character capital L?
90D7 F0 F5 BEQ Q0CE ;if so then set bit 7
90D9 20 51 A3 JSR R351 ;else raise "Bad attribute" error.
90DC EQUB &CF
90DD EQUS "attribute"
90E6 EQUB &00
.Q0E7 ;Raise "Disk full" error.
90E7 20 47 A3 JSR R347
90EA EQUB &C6
90EB EQUS "full"
90EF EQUB &00
.Q0F0 ;Create file from OSFILE block
90F0 20 EB 87 JSR P7EB ;set current file from argument pointer
90F3 20 63 89 JSR P963 ;search for file in catalogue
90F6 90 03 BCC Q0FB ;if found
90F8 20 9E 89 JSR P99E ;then delete catalogue entry
.Q0FB
90FB A5 C2 LDA &C2 ;save start address low word
90FD 48 PHA
90FE A5 C3 LDA &C3
9100 48 PHA
9101 38 SEC ;subtract end address - start address
9102 A5 C4 LDA &C4 ;(24 bits) yielding file length
9104 E5 C2 SBC &C2
9106 85 C2 STA &C2
9108 A5 C5 LDA &C5
910A E5 C3 SBC &C3
910C 85 C3 STA &C3
910E AD 75 10 LDA &1075
9111 ED 73 10 SBC &1073
9114 85 C6 STA &C6
9116 20 2C 91 JSR Q12C ;create catalogue entry
9119 AD 74 10 LDA &1074 ;copy start address high word to data pointer
911C 8D 70 10 STA &1070
911F AD 73 10 LDA &1073
9122 8D 6F 10 STA &106F
9125 68 PLA ;restore low word to data pointer
9126 85 BF STA &BF
9128 68 PLA
9129 85 BE STA &BE
912B 60 RTS
.Q12C ;Create catalogue entry
912C A9 00 LDA #&00
912E 85 C4 STA &C4 ;set MSB of LBA = 0
9130 20 8E 9F JSR QF8E ;return no. reserved sectors in data area
9133 85 C5 STA &C5 ;set as MSB of LBA
9135 AC 05 0F LDY &0F05 ;get number of files in catalogue * 8
9138 C0 F8 CPY #&F8 ;if there are already 31 files
913A B0 4C BCS Q188 ;then raise "Catalogue full" error, else:
913C 20 BA 91 JSR Q1BA ;test if new file will fit at current LBA
913F 4C 4A 91 JMP Q14A ;jump into loop
.Q142
9142 F0 A3 BEQ Q0E7 ;if cat ptr = 0 then raise "Disk full" error
9144 20 7B A4 JSR R47B ;else subtract 8 from Y
9147 20 9B 91 JSR Q19B ;test if new file will fit after current file
.Q14A
914A 98 TYA ;test if catalogue pointer > 0
914B 90 F5 BCC Q142 ;if file won't fit then test prev cat entry
914D 84 B0 STY &B0 ;else insert new catalogue entry here
914F AC 05 0F LDY &0F05 ;point Y to last valid catalogue entry:
.Q152
9152 C4 B0 CPY &B0 ;compare pointer with insertion point
9154 F0 0F BEQ Q165 ;stop copying if insertion point reached
9156 B9 07 0E LDA &0E07,Y ;else copy current catalogue entry
9159 99 0F 0E STA &0E0F,Y ;to next slot
915C B9 07 0F LDA &0F07,Y ;leaving one slot open
915F 99 0F 0F STA &0F0F,Y ;for new catalogue entry
9162 88 DEY ;decrease pointer to work back from end
9163 B0 ED BCS Q152 ;and loop (always)
.Q165
9165 20 F1 91 JSR Q1F1 ;compose top bits exec/length/load/start
9168 20 E3 91 JSR Q1E3 ;write filename+dir into catalogue at Y=0..&F0
.Q16B ;Write load/exec/length/start into catalogue
916B B5 BD LDA &BD,X ;x=8..1 copy from &BE..&C5
916D 88 DEY ;y=catalogue pointer + 7..0
916E 99 08 0F STA &0F08,Y ;copy to catalogue address fields
9171 CA DEX ;loop until 8 bytes copied
9172 D0 F7 BNE Q16B
9174 20 BB 89 JSR P9BB ;print *INFO line if verbose
9177 98 TYA ;save catalogue pointer
9178 48 PHA
9179 AC 05 0F LDY &0F05 ;get number of files in catalogue * 8
917C 20 72 A4 JSR R472 ;add 8 to Y
917F 8C 05 0F STY &0F05 ;store new file count
9182 20 81 92 JSR Q281 ;write volume catalogue
9185 68 PLA ;restore catalogue pointer
9186 A8 TAY
9187 60 RTS
.Q188 ;Raise "Catalogue full" error.
9188 20 62 A3 JSR R362
918B EQUB &BE
918C EQUS "Catalogue full"
919A EQUB &00
.Q19B ;Test if new file will fit after current file
919B B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
919E 20 5F A4 JSR R45F ;extract b5,b4 of A = MSB length
91A1 85 C4 STA &C4 ;save length in zero page (big-endian)
91A3 18 CLC
91A4 A9 FF LDA #&FF ;subtract 1 from LSB length
91A6 79 0C 0F ADC &0F0C,Y ;setting C=1 if file includes partial sector
91A9 B9 0F 0F LDA &0F0F,Y ;add LSB start LBA + 2MSB length + C
91AC 79 0D 0F ADC &0F0D,Y ;=LSB LBA after last sector of file
91AF 85 C5 STA &C5 ;save LBA in zero page (big-endian)
91B1 B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
91B4 29 03 AND #&03 ;extract MSB start LBA
91B6 65 C4 ADC &C4 ;add MSB start LBA + MSB length + C
91B8 85 C4 STA &C4 ;=MSB LBA after last sector of file:
.Q1BA ;Test if new file will fit at current LBA
91BA A5 C5 LDA &C5 ;save LSB current LBA
91BC 48 PHA
91BD 38 SEC ;subtract LSBs LBA of file - current LBA
91BE B9 07 0F LDA &0F07,Y
91C1 E5 C5 SBC &C5
91C3 85 C5 STA &C5 ;=LSB no. free sectors after file
91C5 B9 06 0F LDA &0F06,Y ;get top bits exec/length/load/start sector
91C8 29 03 AND #&03 ;extract MSB start LBA
91CA E5 C4 SBC &C4 ;subtract MSB current LBA
91CC AA TAX ;=MSB no. free sectors after file
91CD 05 C5 ORA &C5 ;are there any free sectors?
91CF D0 03 BNE Q1D4 ;if so compare with file sector size
91D1 18 CLC ;else return C=0 file won't fit.
91D2 90 0B BCC Q1DF ;[BUG] empty files don't fit on a full disc
.Q1D4
91D4 A9 00 LDA #&00 ;set C=1 if LSB length = 0, no borrow:
91D6 C5 C2 CMP &C2
91D8 A5 C5 LDA &C5 ;subtract LSB free sectors - 2MSB length
91DA E5 C3 SBC &C3
91DC 8A TXA ;subtract MSB free sectors - MSB length
91DD E5 C6 SBC &C6 ;return C = 1 if file fits in free space
.Q1DF
91DF 68 PLA ;restore LSB current LBA
91E0 85 C5 STA &C5
91E2 60 RTS
.Q1E3 ;Write filename+dir into catalogue at Y=0..&F0
91E3 A2 00 LDX #&00
.Q1E5
91E5 B5 C7 LDA &C7,X ;get character of current filename+dir
91E7 99 08 0E STA &0E08,Y ;store in catalogue
91EA C8 INY ;increment both offsets
91EB E8 INX
91EC E0 08 CPX #&08 ;loop until 8 bytes copied.
91EE D0 F5 BNE Q1E5
91F0 60 RTS
.Q1F1 ;Compose top bits exec/length/load/start
91F1 AD 71 10 LDA &1071 ;get b17,b16 exec address
91F4 29 03 AND #&03 ;place in b1,b0 of A, clear b7..b2
91F6 0A ASL A ;shift A left 2 places
91F7 0A ASL A ;a = ....ee..
91F8 45 C6 EOR &C6 ;place b17,b16 of length in b1,b0
91FA 29 FC AND #&FC ;keep b7..b2 of A
91FC 45 C6 EOR &C6 ;a = ....eell
91FE 0A ASL A ;shift A left 2 places
91FF 0A ASL A ;a = ..eell..
9200 4D 6F 10 EOR &106F ;place b17,b16 of load address in b1,b0
9203 29 FC AND #&FC ;keep b7..b2 of A
9205 4D 6F 10 EOR &106F ;a = ..eelldd
9208 0A ASL A ;shift A left 2 places
9209 0A ASL A ;a = eelldd..
920A 45 C4 EOR &C4 ;place b10,b9 of start LBA in b1,b0
920C 29 FC AND #&FC ;keep b7..b2 of A
920E 45 C4 EOR &C4 ;a = eellddss
9210 85 C4 STA &C4 ;set top bits exec/length/load/start sector
9212 60 RTS
;*ENABLE
9213 A9 01 LDA #&01 ;set *ENABLE flag = 1; will be nonnegative
9215 8D D2 10 STA &10D2 ;(after OSFSC 8) for next *command only.
9218 60 RTS
.Q219 ;Expand 18-bit load address to 32-bit
9219 48 PHA
921A A9 00 LDA #&00 ;set MSB of address = &00
921C 48 PHA
921D A5 C4 LDA &C4
921F 20 61 A4 JSR R461 ;extract b3,b2 of A
9222 C9 03 CMP #&03 ;if either bit clear then a Tube address
9224 D0 06 BNE Q22C ;so set high word = high word of tube address
9226 68 PLA ;else discard the high word:
9227 68 PLA
.Q228 ;Set high word of OSFILE load address = &FFFF
9228 48 PHA
9229 A9 FF LDA #&FF
922B 48 PHA
.Q22C ;Set high word of OSFILE load address
922C 8D 6F 10 STA &106F
922F 68 PLA
9230 8D 70 10 STA &1070
9233 68 PLA
9234 60 RTS
.Q235 ;Expand 18-bit exec address to 32-bit
9235 A9 00 LDA #&00 ;clear MSB of 32-bit address
9237 8D 72 10 STA &1072
923A A5 C4 LDA &C4
923C 20 5D A4 JSR R45D ;extract b7,b6 of A
923F C9 03 CMP #&03 ;if b7,b6 both set
9241 D0 05 BNE Q248
9243 A9 FF LDA #&FF ;then a host address, set high word = &FFFF
9245 8D 72 10 STA &1072
.Q248
9248 8D 71 10 STA &1071 ;else set 2MSB parasite address &0..2FFFF
924B 60 RTS
;*RENAME
924C 20 2F 89 JSR P92F ;disallow wildcard characters in filename
924F 20 EA 8F JSR PFEA ;set current file from argument
9252 A5 CF LDA &CF ;get current volume
9254 48 PHA
9255 98 TYA ;save command line offset
9256 48 PHA
9257 20 3E 89 JSR P93E ;ensure matching file in catalogue
925A 20 F8 9B JSR QBF8 ;ensure file not locked or open (mutex)
925D 84 B3 STY &B3
925F 68 PLA ;restore command line offset
9260 A8 TAY
9261 20 EA 8F JSR PFEA ;set current file from argument
9264 68 PLA ;restore current volume
9265 C5 CF CMP &CF ;compare with destination volume
9267 F0 03 BEQ Q26C ;if equal then rename the file
9269 4C F8 94 JMP Q4F8 ;else rename across volumes, "Bad command".
.Q26C
926C 20 63 89 JSR P963 ;search for file in catalogue
926F 90 0B BCC Q27C ;if not found then update filename+dir
9271 20 5A A3 JSR R35A ;else raise "File exists" error.
9274 EQUB &C4
9275 EQUS "exists"
927B EQUB &00
.Q27C ;Update filename+dir in catalogue
927C A4 B3 LDY &B3 ;get pointer to file entry
927E 20 E3 91 JSR Q1E3 ;write filename+dir into catalogue:
.Q281
9281 18 CLC ;Write volume catalogue L4
9282 F8 SED ;add 1 to BCD catalogue cycle number
9283 AD 04 0F LDA &0F04
9286 69 01 ADC #&01
9288 8D 04 0F STA &0F04
928B D8 CLD
928C 20 5E 93 JSR Q35E ;set &1000 = write, claim NMI
928F 4C A4 92 JMP Q2A4 ;transfer volume catalogue and exit
.Q292 ;Ensure current volume catalogue loaded
9292 AD 84 10 LDA &1084 ;get drive and volume of loaded catalogue
9295 C5 CF CMP &CF ;compare with current drive and volume
9297 D0 05 BNE Q29E ;if unequal then load volume catalogue
#if defined _DDOS316
9299 20 E0 B9 JSR S9E0 ;load FDC status register
#elif defined _DDOS336
9299 20 D8 B9 JSR S9D8 ;load FDC status register
#else
9299 20 FB B9 JSR S9FB ;load FDC status register
#endif
929C F0 25 BEQ Q2C3 ;if motor is on then finish
.Q29E
929E 20 00 A3 JSR R300 ;else save AXY
.Q2A1 ;Load volume catalogue L4
92A1 20 55 93 JSR Q355 ;set &1000 = read, claim NMI:
.Q2A4 ;Transfer volume catalogue
92A4 A9 00 LDA #&00
92A6 8D D5 10 STA &10D5
92A9 20 D6 A7 JSR R7D6 ;set up for current drive
92AC 20 A4 A5 JSR R5A4 ;detect disc format/set sector address
92AF A5 CF LDA &CF ;get current volume
92B1 8D 84 10 STA &1084 ;set drive and volume of loaded catalogue
92B4 20 D3 92 JSR Q2D3 ;transfer disc/volume catalogue L3
92B7 F0 0A BEQ Q2C3 ;if zero status release NMI and exit
92B9 29 40 AND #&40
92BB D0 03 BNE Q2C0 ;else if b6=0 WD1770 S6 = write protect
#if defined _DDOS316
92BD 4C 95 B9 JMP S995 ;then raise "Disk fault" error
#elif defined _DDOS336
92BD 4C 93 B9 JMP S993 ;then raise "Disk fault" error
#else
92BD 4C B6 B9 JMP S9B6 ;then raise "Disk fault" error
#endif
.Q2C0
92C0 4C 38 A3 JMP R338 ;else raise "Disk read only" error.
.Q2C3
92C3 4C A7 A7 JMP R7A7 ;release NMI and exit.
;unreachable code
92C6 A9 00 LDA #&00 ;data transfer call &01 = write data
92C8 8D 00 10 STA &1000 ;set data transfer call number
92CB 4C D3 92 JMP Q2D3 ;transfer disc/volume catalogue L3
.Q2CE ;Write disc/volume catalogue L3
92CE A9 01 LDA #&01 ;data transfer call &01 = write data
92D0 8D 00 10 STA &1000 ;set data transfer call number
.Q2D3 ;Transfer disc/volume catalogue L3
92D3 20 29 A3 JSR R329 ;save XY
92D6 20 ED 92 JSR Q2ED ;set data pointer to &0E00
92D9 A2 03 LDX #&03 ;set X = &03, three possible attempts:
.Q2DB
92DB A9 00 LDA #&00 ;512 bytes to transfer
92DD 85 A0 STA &A0
92DF A9 02 LDA #&02
92E1 85 A1 STA &A1
92E3 20 67 B4 JSR S467 ;transfer data L2
92E6 F0 04 BEQ Q2EC ;if zero status then success, return
92E8 CA DEX ;else decrement attempts counter
92E9 D0 F0 BNE Q2DB ;if not tried 3 times then try again
92EB CA DEX
.Q2EC
92EC 60 RTS
.Q2ED ;Set data pointer to &0E00
92ED A9 00 LDA #&00
92EF 85 A6 STA &A6
92F1 A9 0E LDA #&0E
92F3 85 A7 STA &A7
92F5 60 RTS
#if defined _BUGFIX
.Q2F6
92F6 48 PHA ;save FDC command
92F7 A9 40 LDA #&40 ;instruction at &0D00 = RTI
92F9 8D 00 0D STA &0D00
92FC 68 PLA ;restore FDC command
# if defined _DDOS316
92FD 4C BB B6 JMP S6BB ;and write it to command register
# elif defined _DDOS316
92FD 4C BB B6 JMP S6BB ;and write it to command register
# else
92FD 4C B9 B6 JMP S6B9 ;and write it to command register
# endif
#else
;unreachable code
92F6 AD 82 10 LDA &1082 ;load Tube call number
92F9 48 PHA
92FA AD D5 10 LDA &10D5 ;load Tube flag, A>0 if Tube in use
92FD 4C 1C 93 JMP Q31C ;call Tube service
#endif
.Q300 ;Open Tube data transfer channel
9300 48 PHA
9301 8D 82 10 STA &1082 ;a=Tube service call, save in stack and wksp
9304 A5 BE LDA &BE ;reform address at &106D..70 from &BE,F
9306 8D 6D 10 STA &106D
9309 A5 BF LDA &BF
930B 8D 6E 10 STA &106E
930E AD 6F 10 LDA &106F ;and high bytes of address
9311 2D 70 10 AND &1070 ;a=&FF if address is in the host
9314 0D D6 10 ORA &10D6 ;a=&FF if Tube absent (&10D6=NOT MOS flag!)
9317 49 FF EOR #&FF ;invert; A>0 if transferring over Tube
9319 8D D5 10 STA &10D5 ;store Tube flag
.Q31C ;Call Tube service, Z=1 if Tube unused
931C 38 SEC
931D F0 0D BEQ Q32C ;if A=0 then no need for Tube, exit C=1
931F 20 2E 93 JSR Q32E ;else claim Tube
9322 A2 6D LDX #&6D ;point XY at address
9324 A0 10 LDY #&10
9326 68 PLA ;restore Tube call number
9327 48 PHA
9328 20 06 04 JSR &0406 ;call Tube service
932B 18 CLC ;exit C=0 as Tube was called
.Q32C
932C 68 PLA ;preserve Tube call number on exit
932D 60 RTS
.Q32E ;Claim Tube
932E 48 PHA
.Q32F
932F A9 C1 LDA #&C1 ;tube service call = &C0 + ID for DFS (1)
9331 20 06 04 JSR &0406 ;call Tube service
9334 90 F9 BCC Q32F ;loop until C=1, indicating claim granted
9336 68 PLA
9337 60 RTS
.Q338 ;Release Tube
9338 48 PHA
9339 AD D5 10 LDA &10D5 ;load Tube flag, A>0 if Tube in use
933C F0 05 BEQ Q343 ;if not in use then exit, else:
.Q33E
933E A9 81 LDA #&81 ;tube service call = &80 + ID for DFS (1)
9340 20 06 04 JSR &0406 ;call Tube service
.Q343
9343 68 PLA
9344 60 RTS
.Q345 ;Release Tube if present
9345 48 PHA
9346 A9 EA LDA #&EA ;OSBYTE &EA = read Tube presence flag
9348 20 1E A8 JSR R81E ;call OSBYTE with X=0, Y=&FF
934B 8A TXA ;test X, X=&FF if Tube present
934C D0 F0 BNE Q33E ;if Tube present then release Tube
934E 68 PLA
934F 60 RTS
.Q350 ;Prepare to read to user memory
9350 A9 01 LDA #&01 ;Tube service 1 = write single bytes to R3
9352 20 00 93 JSR Q300 ;open Tube data transfer channel
.Q355
9355 A9 00 LDA #&00 ;data transfer call &00 = read data
9357 F0 07 BEQ Q360 ;branch (always)
.Q359 ;Prepare to write from user memory
9359 A9 00 LDA #&00 ;Tube service 0 = read single bytes from R3
935B 20 00 93 JSR Q300 ;open Tube data transfer channel
.Q35E
935E A9 01 LDA #&01 ;data transfer call &01 = write data
.Q360
9360 8D 00 10 STA &1000 ;set data transfer call number
9363 20 C1 A7 JSR R7C1 ;claim NMI
9366 A9 FF LDA #&FF
9368 8D 84 10 STA &1084 ;no catalogue in pages &0E..F
936B 60 RTS
;*TAPEDISK
936C 20 E2 A2 JSR R2E2 ;save XY
936F 8E EE 02 STX &02EE ;store filename address in MOS OSFILE block
9372 8C EF 02 STY &02EF
9375 20 AC 9F JSR QFAC ;get start and size of user memory
9378 AD 89 10 LDA &1089 ;get start of user memory
937B 8D F1 02 STA &02F1 ;set as load address of OSFILE block
937E A9 00 LDA #&00 ;loading starts on page boundary
9380 8D F0 02 STA &02F0 ;[BUG] loads to coprocessor memory!
9383 20 09 94 JSR Q409 ;clear top of MOS OSFILE block
9386 A2 0C LDX #&0C ;x = &0C 1200 baud
9388 A9 8C LDA #&8C ;OSBYTE &8C = *TAPE
938A 20 F4 FF JSR &FFF4 ;call OSBYTE
938D A9 FF LDA #&FF ;a=&FF load file
938F 20 02 94 JSR Q402 ;call OSFILE using MOS OSFILE block
9392 A2 16 LDX #&16 ;point XY to *DISC command
9394 A0 94 LDY #&94
9396 20 F7 FF JSR &FFF7 ;call OSCLI
9399 A9 B2 LDA #&B2 ;point filename field to last read CFS block
939B 8D EE 02 STA &02EE ;&03B2 begins with NUL-terminated filename
939E A9 03 LDA #&03
93A0 8D EF 02 STA &02EF
93A3 A2 00 LDX #&00
.Q3A5
93A5 BD B2 03 LDA &03B2,X ;scan filename of last CFS block read
93A8 F0 05 BEQ Q3AF ;until NUL found
93AA E8 INX
93AB E0 07 CPX #&07 ;or 7 characters scanned
93AD D0 F6 BNE Q3A5 ;(no allowance for directory specifiers)
.Q3AF
93AF A9 0D LDA #&0D ;terminate filename with CR
93B1 9D B2 03 STA &03B2,X
93B4 20 1B 94 JSR Q41B ;calculate CFS file length
93B7 A5 B0 LDA &B0 ;round up to whole number of pages in &B1
93B9 F0 02 BEQ Q3BD
93BB E6 B1 INC &B1
.Q3BD
93BD AD 8B 10 LDA &108B ;compare available memory - file size
93C0 C5 B1 CMP &B1
93C2 B0 13 BCS Q3D7 ;if file fit in memory then continue
93C4 20 5A A3 JSR R35A ;else "File size too large" error (too late!)
93C7 EQUB &D4
93C8 EQUS "size too large"
93D6 EQUB &00
.Q3D7
93D7 20 1B 94 JSR Q41B ;calculate CFS file length
93DA A9 00 LDA #&00 ;set OSFILE start address = start of user mem
93DC 8D F8 02 STA &02F8
93DF AD 89 10 LDA &1089
93E2 8D F9 02 STA &02F9
93E5 18 CLC ;set end address = start addr + length of file
93E6 65 B1 ADC &B1
93E8 8D FD 02 STA &02FD
93EB A5 B0 LDA &B0
93ED 8D FC 02 STA &02FC
93F0 A9 00 LDA #&00 ;a=&00 save file
93F2 20 02 94 JSR Q402 ;call OSFILE using MOS OSFILE block
93F5 A2 07 LDX #&07 ;8 bytes to copy, 7..0:
.Q3F7
93F7 BD BE 03 LDA &03BE,X ;copy load and exec addresses from CFS block
93FA 9D F0 02 STA &02F0,X ;to OSFILE block
93FD CA DEX
93FE 10 F7 BPL Q3F7
9400 A9 01 LDA #&01 ;a=&01 write catalogue information:
.Q402 ;Call OSFILE using MOS OSFILE block
9402 A2 EE LDX #&EE
9404 A0 02 LDY #&02
9406 4C DD FF JMP &FFDD
.Q409 ;Clear top of MOS OSFILE block
9409 A2 04 LDX #&04 ;start at top half of load address field
940B A9 00 LDA #&00 ;a=&00 write zeroes
.Q40D
940D 9D EE 02 STA &02EE,X ;clear load, exec, length, attribute fields
9410 E8 INX
9411 E0 11 CPX #&11
9413 90 F8 BCC Q40D
9415 60 RTS
9416 EQUS "DISC" ;*DISC command string
941A EQUB &0D
.Q41B ;Calculate CFS file length
941B AD C8 03 LDA &03C8 ;get LSB length of last block of file
941E 85 B0 STA &B0 ;store LSB length of file
9420 18 CLC ;set c=0
9421 AD C6 03 LDA &03C6 ;get LSB number of last block
9424 6D C9 03 ADC &03C9 ;add MSB length of file (0 or 1)
9427 85 B1 STA &B1 ;store MSB length of file
9429 60 RTS
;*ROMID
942A 20 F3 A2 JSR R2F3 ;have A=0 returned on exit
942D AD 99 A8 LDA &A899 ;get version number integer part
9430 18 CLC ;C=0 to enable space padding
9431 20 B4 A2 JSR R2B4 ;print hex byte, C=0 if space-padded
9434 20 01 A4 JSR R401 ;print a dot
9437 AD 9A A8 LDA &A89A ;get version number decimal part
943A 20 29 A4 JSR R429 ;print hex byte
943D 20 C9 A2 JSR R2C9 ;print two spaces
9440 A0 02 LDY #&02 ;repeat with offset 2..4:
.Q442
9442 B9 99 A8 LDA &A899,Y ;get byte of release date dd/mm/yy
9445 20 29 A4 JSR R429 ;print hex byte
9448 C8 INY
9449 C0 05 CPY #&05 ;move on at offset 5
944B F0 08 BEQ Q455
944D A9 2D LDA #&2D ;else print a dash
944F 20 03 A4 JSR R403
9452 4C 42 94 JMP Q442 ;and loop
.Q455
9455 20 CC A2 JSR R2CC ;print a space
9458 18 CLC ;C=0 to enable space padding
9459 A2 03 LDX #&03 ;repeat with offsets 5..7:
.Q45B
945B B9 99 A8 LDA &A899,Y ;get byte of release number
945E 20 B4 A2 JSR R2B4 ;print hex byte, C=0 if space-padded
9461 C8 INY ;increment offset
9462 CA DEX ;decrement counter
9463 D0 F6 BNE Q45B ;loop until 3 bytes printed
9465 4C 67 84 JMP P467 ;print newline and exit
#if defined _DDOS357
.Q468
#endif
;OSFSC
9468 C9 09 CMP #&09 ;if call outside range 0..8
946A B0 0E BCS Q47A ;then exit
946C 86 B5 STX &B5 ;else save X
946E AA TAX ;transfer call number to X as index
946F BD 4A A8 LDA &A84A,X ;get action address high byte
9472 48 PHA ;save on stack
9473 BD 41 A8 LDA &A841,X ;get action address low byte
9476 48 PHA ;save on stack
9477 8A TXA ;restore call number to A
9478 A6 B5 LDX &B5 ;restore X on entry
.Q47A
947A 60 RTS ;jump to action address
;OSFSC 0 = *OPT
947B 20 00 A3 JSR R300 ;save AXY
947E 8A TXA
947F C9 04 CMP #&04 ;is it *OPT 4?
9481 F0 19 BEQ Q49C ;if so go and set boot option
9483 C9 02 CMP #&02 ;else is it *OPT 0 or *OPT 1?
9485 90 0B BCC Q492 ;if so go and set monitoring option
9487 20 51 A3 JSR R351 ;else raise "Bad option" error.
948A EQUB &CB
948B EQUS "option"
9491 EQUB &00
.Q492 ;*OPT 0 / *OPT 1 monitor
9492 A2 FF LDX #&FF
9494 98 TYA ;is verbosity level =0?
9495 F0 01 BEQ Q498 ;if so then set flag = &FF
9497 E8 INX ;else level >0, set flag = 0.
.Q498
9498 8E D1 10 STX &10D1
949B 60 RTS
.Q49C ;*OPT 4 set boot option
949C 98 TYA ;save requested option
949D 48 PHA
949E 20 FB A4 JSR R4FB ;set current vol/dir = default, set up drive
94A1 20 A1 92 JSR Q2A1 ;load volume catalogue
94A4 68 PLA ;restore option
94A5 20 6D A4 JSR R46D ;shift A left 4 places
94A8 4D 06 0F EOR &0F06 ;xor new option with old
94AB 29 30 AND #&30 ;clear all but option bits 5,4
94AD 4D 06 0F EOR &0F06 ;b5,4 contain new option, others preserved
94B0 8D 06 0F STA &0F06 ;store new option in catalogue
94B3 4C 81 92 JMP Q281 ;write volume catalogue and exit.
;OSFSC 1 = read EOF state
94B6 48 PHA
94B7 98 TYA
94B8 48 PHA
94B9 8A TXA
94BA A8 TAY
94BB 20 A7 98 JSR Q8A7 ;ensure file handle valid and open
94BE 98 TYA ;a=y = channel workspace pointer
94BF 20 B4 9A JSR QAB4 ;compare PTR - EXT
94C2 D0 04 BNE Q4C8 ;if PTR <> EXT (blech!) then return 0
94C4 A2 FF LDX #&FF ;else return &FF, we are at end of file
94C6 D0 02 BNE Q4CA
.Q4C8
94C8 A2 00 LDX #&00
.Q4CA
94CA 68 PLA
94CB A8 TAY
94CC 68 PLA
94CD 60 RTS
;OSFSC 2 = */; OSFSC 4 = *RUN
94CE 20 42 8F JSR PF42 ;set GSINIT pointer to XY, set Y=0
;OSFSC 3 with *command not in table
94D1 20 3E 95 JSR Q53E ;copy argument ptr and load to cat address
94D4 8C DA 10 STY &10DA ;store offset of start of command line
94D7 20 EB 87 JSR P7EB ;set current file from argument pointer
94DA 8C D9 10 STY &10D9 ;store offset of command line tail
94DD 20 63 89 JSR P963 ;search for file in catalogue
94E0 B0 22 BCS Q504 ;if found then execute command binary
94E2 AC DA 10 LDY &10DA
94E5 AD CC 10 LDA &10CC ;get library directory
94E8 85 CE STA &CE ;set as current directory
94EA AD CD 10 LDA &10CD ;get library drive and volume
94ED 20 03 A5 JSR R503 ;select volume in A
94F0 20 EE 87 JSR P7EE ;parse file spec from argument pointer
94F3 20 63 89 JSR P963 ;search for file in catalogue
94F6 B0 0C BCS Q504 ;if found then execute it
.Q4F8
94F8 20 51 A3 JSR R351 ;else raise "Bad command" error.
94FB EQUB &FE
94FC EQUS "command"
9503 EQUB &00
.Q504 ;Execute command binary
9504 20 5F 9B JSR QB5F ;load file into memory
9507 18 CLC
9508 AD D9 10 LDA &10D9 ;get offset of command line tail
950B A8 TAY ;and pass to command in Y (if on host)
950C 65 F2 ADC &F2 ;add it to GSINIT pointer in &F2,3
950E 8D D9 10 STA &10D9 ;giving command line tail pointer
9511 A5 F3 LDA &F3 ;save it in &10D9,A for OSARGS 1
9513 69 00 ADC #&00
9515 8D DA 10 STA &10DA
9518 AD 71 10 LDA &1071 ;and high bytes of address
951B 2D 72 10 AND &1072 ;a=&FF if address is in the host
951E 0D D6 10 ORA &10D6 ;a=&FF if Tube absent (&10D6=NOT MOS flag!)
9521 C9 FF CMP #&FF ;if host address or Tube absent
9523 F0 16 BEQ Q53B ;then jump indirect
9525 A5 C0 LDA &C0 ;else copy low word of exec address
9527 8D 6F 10 STA &106F ;over high word of load addr in OSFILE block
952A A5 C1 LDA &C1
952C 8D 70 10 STA &1070
952F 20 2E 93 JSR Q32E ;claim Tube
9532 A2 6F LDX #&6F ;point XY to 32-bit execution address
9534 A0 10 LDY #&10
9536 A9 04 LDA #&04 ;tube service call &04 = *Go
9538 4C 06 04 JMP &0406 ;jump into Tube service
.Q53B
953B 6C C0 00 JMP (&00C0) ;Execute command on host
.Q53E ;Copy argument ptr and load to cat address
953E A9 FF LDA #&FF ;lsb exec address in our OSFILE block = &FF:
9540 85 C0 STA &C0 ;load executable to load address in catalogue
9542 A5 F2 LDA &F2 ;copy GSINIT string pointer to zero page
9544 85 BC STA &BC ;= command line pointer
9546 A5 F3 LDA &F3
9548 85 BD STA &BD
954A 60 RTS
;OSFSC 3 = unrecognised *command
954B 20 42 8F JSR PF42 ;set GSINIT pointer to XY, set Y=0
954E A2 8A LDX #&8A ;point XY to command table at &8D8A
9550 A0 8D LDY #&8D
9552 A9 00 LDA #&00
9554 20 C7 8E JSR PEC7 ;search for command or keyword in table
9557 BA TSX
9558 86 B8 STX &B8
#if defined _DDOS357
955A 4C C9 80 JMP P0C9 ;*command while FSCV does not point to us
#else
955A 4C CC 80 JMP P0CC ;*command while FSCV does not point to us
#endif
;OSFSC 5 = *CAT
955D 20 42 8F JSR PF42 ;set GSINIT pointer to XY, set Y=0
9560 20 E5 A4 JSR R4E5 ;select specified or default volume
.Q563
9563 20 92 92 JSR Q292 ;ensure current volume catalogue loaded
9566 20 D6 8B JSR PBD6 ;print volume title
9569 20 00 8C JSR PC00 ;print disc type and volume list
956C 20 7F 8C JSR PC7F ;print volume spec and boot option
956F 20 B7 8C JSR PCB7 ;print CSD and library directories
9572 4C 02 8B JMP PB02 ;list files in catalogue
.Q575 ;OSFSC 6 = new filing system starting up
9575 20 00 A3 JSR R300 ;save AXY
9578 A9 77 LDA #&77 ;call OSBYTE &77 = close *SPOOL/*EXEC files
957A 4C F4 FF JMP &FFF4
;OSFSC 7 = return range of valid file handles
957D A2 11 LDX #&11
957F A0 15 LDY #&15
9581 60 RTS
;OSFSC 8 = *command has been entered
9582 2C D2 10 BIT &10D2 ;if *ENABLEd flag b7=0 (i.e. byte = 0 or 1)
9585 30 03 BMI Q58A
9587 CE D2 10 DEC &10D2 ;then enable this command, not the ones after
.Q58A
958A A9 FF LDA #&FF
958C 8D 84 10 STA &1084 ;no catalogue in pages &0E..F
958F 60 RTS
.Q590 ;Ensure open file still in drive
9590 20 97 A5 JSR R597 ;set current vol/dir from open filename
.Q593 ;Ensure open file still on current volume
9593 A2 07 LDX #&07 ;start at seventh character of leaf name:
.Q595
9595 B9 0C 11 LDA &110C,Y ;copy leaf name of file to current leaf name
9598 95 C6 STA &C6,X
959A 88 DEY ;skip odd bytes containing length and addrs
959B 88 DEY ;select previous character of leaf name (Y>0)
959C CA DEX ;decrement offset in current leaf name
959D D0 F6 BNE Q595 ;loop until 7 characters copied (X=7..1)
959F 20 63 89 JSR P963 ;search for file in catalogue
95A2 90 1A BCC Q5BE ;if file not found then raise "Disk changed"
95A4 8C C7 10 STY &10C7 ;else save offset in catalogue
95A7 B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
95AA BE 0F 0F LDX &0F0F,Y ;put LSB start sector in X
95AD AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
95B0 59 0D 11 EOR &110D,Y ;compare start sector with one in workspace
95B3 29 03 AND #&03 ;mask off other fields
95B5 D0 07 BNE Q5BE ;if not equal then raise "Disk changed" error
95B7 8A TXA ;else compare low bytes of start sector (LBA)
95B8 D9 0F 11 CMP &110F,Y
95BB D0 01 BNE Q5BE ;if not equal then raise "Disk changed" error
95BD 60 RTS ;else exit
.Q5BE
95BE 4C 95 88 JMP P895 ;raise "Disk changed" error
#if defined _DFSFIX
.Q5C1
#endif
;OSFIND
95C1 C9 00 CMP #&00
95C3 D0 62 BNE Q627 ;if A>0 then open a file
95C5 20 00 A3 JSR R300 ;else close a file/all files. save AXY
.Q5C8
95C8 98 TYA ;if handle = 0
95C9 F0 08 BEQ Q5D3 ;then close all files
95CB 20 93 98 JSR Q893 ;else convert to pointer, if valid (&11..17)
95CE 90 12 BCC Q5E2 ;then close file
95D0 4C C6 98 JMP Q8C6 ;else raise "Channel" error.
.Q5D3
95D3 20 75 95 JSR Q575 ;Close all files: close *SPOOL/*EXEC files
.Q5D6
95D6 A9 A0 LDA #&A0 ;set channel workspace pointer = &A0:
.Q5D8
95D8 A8 TAY ;transfer channel workspace pointer to Y
95D9 20 E2 95 JSR Q5E2 ;close file
95DC 38 SEC ;subtract &20 to point to next channel
95DD E9 20 SBC #&20
95DF D0 F7 BNE Q5D8 ;if >0 then loop (close 5 files &A0..20).
95E1 60 RTS
.Q5E2 ;Close file L7
95E2 48 PHA
95E3 20 63 98 JSR Q863 ;validate workspace offset
95E6 B0 3A BCS Q622 ;if it points to channel &10 then exit
95E8 B9 1B 11 LDA &111B,Y ;else get bit mask corresponding to channel
95EB 49 FF EOR #&FF ;invert it, bit corresponding to channel =0
95ED 2D C3 10 AND &10C3 ;clear bit of channel open flag byte
95F0 8D C3 10 STA &10C3 ;update flag byte
95F3 B9 17 11 LDA &1117,Y ;get channel flags
95F6 29 60 AND #&60 ;if either buffer or EXT changed
95F8 F0 28 BEQ Q622
95FA 20 90 95 JSR Q590 ;then ensure open file still in drive
95FD B9 17 11 LDA &1117,Y ;if EXT changed
9600 29 20 AND #&20
9602 F0 1B BEQ Q61F
9604 AE C7 10 LDX &10C7 ;then set X = catalogue pointer
9607 B9 14 11 LDA &1114,Y ;copy low word of EXT to length in catalogue
960A 9D 0C 0F STA &0F0C,X
960D B9 15 11 LDA &1115,Y
9610 9D 0D 0F STA &0F0D,X
9613 B9 16 11 LDA &1116,Y ;get high byte of EXT
9616 20 F0 8F JSR PFF0 ;pack b17,16 of length into catalogue entry
9619 20 81 92 JSR Q281 ;write volume catalogue
961C AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
.Q61F
961F 20 51 99 JSR Q951 ;ensure buffer up-to-date on disc L6
.Q622
9622 AE C9 10 LDX &10C9 ;restore X on entry
9625 68 PLA ;restore A on entry
9626 60 RTS
.Q627 ;Open a file
9627 20 29 A3 JSR R329 ;save XY
962A 86 BC STX &BC
962C 84 BD STY &BD
962E 85 B4 STA &B4
9630 24 B4 BIT &B4
9632 08 PHP
9633 20 EB 87 JSR P7EB ;set current file from argument pointer
9636 20 32 97 JSR Q732 ;find unused file handle
9639 90 18 BCC Q653 ;if all file handles in use
963B 20 62 A3 JSR R362 ;then raise "Too many files open" error.
963E EQUB &C0
963F EQUS "Too many files open"
9652 EQUB &00
.Q653
9653 A2 C7 LDX #&C7 ;point XY+A to current filename
9655 A9 00 LDA #&00
9657 A8 TAY
9658 20 53 97 JSR Q753 ;compare filename at XY+A with open filenames
965B 90 17 BCC Q674 ;if file not open then continue
.Q65D
965D B9 0C 11 LDA &110C,Y ;else test if the channel is open read-write
9660 10 04 BPL Q666 ;if so, reopening is a conflict; raise error
9662 28 PLP ;else if reopening a r-o channel read-only
9663 08 PHP ;(i.e. channel b7=1, OSFIND call no. b7=0)
9664 10 09 BPL Q66F ;then this is also safe; continue
.Q666
9666 20 5A A3 JSR R35A ;else reopening a r-o channel r-w is conflict
9669 EQUB &C2 ;raise "File open" error.
966A EQUS "open"
966E EQUB &00
.Q66F
966F 20 6A 97 JSR Q76A ;find any other channels open on this file
9672 B0 E9 BCS Q65D ;if another channel found then loop
.Q674
9674 20 2F 89 JSR P92F ;disallow wildcard characters in filename
9677 20 63 89 JSR P963 ;search for file in catalogue
967A B0 18 BCS Q694
967C A9 00 LDA #&00
967E 28 PLP
967F 50 01 BVC Q682
9681 60 RTS
.Q682
9682 08 PHP
9683 A2 07 LDX #&07
.Q685
9685 95 BE STA &BE,X
9687 9D 6F 10 STA &106F,X
968A CA DEX
968B 10 F8 BPL Q685
968D A9 40 LDA #&40
968F 85 C5 STA &C5
9691 20 F0 90 JSR Q0F0 ;create file from OSFILE block
.Q694
9694 98 TYA
9695 AA TAX
9696 28 PLP
9697 08 PHP
9698 70 03 BVS Q69D
969A 20 E8 9B JSR QBE8 ;ensure file not locked
.Q69D
969D A9 08 LDA #&08
969F 8D C8 10 STA &10C8
96A2 AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
.Q6A5
96A5 BD 08 0E LDA &0E08,X
96A8 99 00 11 STA &1100,Y
96AB C8 INY
96AC BD 08 0F LDA &0F08,X
96AF 99 00 11 STA &1100,Y
96B2 C8 INY
96B3 E8 INX
96B4 CE C8 10 DEC &10C8
96B7 D0 EC BNE Q6A5
96B9 A2 10 LDX #&10
96BB A9 00 LDA #&00
.Q6BD
96BD 99 00 11 STA &1100,Y
96C0 C8 INY
96C1 CA DEX
96C2 D0 F9 BNE Q6BD
96C4 AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
96C7 98 TYA
96C8 20 66 A4 JSR R466 ;shift A right 5 places
96CB 69 11 ADC #&11
96CD 99 13 11 STA &1113,Y
96D0 AD C4 10 LDA &10C4
96D3 99 1B 11 STA &111B,Y
96D6 0D C3 10 ORA &10C3
96D9 8D C3 10 STA &10C3
96DC B9 09 11 LDA &1109,Y
96DF 69 FF ADC #&FF
96E1 B9 0B 11 LDA &110B,Y
96E4 69 00 ADC #&00
96E6 99 19 11 STA &1119,Y
96E9 B9 0D 11 LDA &110D,Y
96EC 09 0F ORA #&0F
96EE 69 00 ADC #&00
96F0 20 5F A4 JSR R45F ;extract b5,b4 of A
96F3 99 1A 11 STA &111A,Y
96F6 28 PLP
96F7 50 32 BVC Q72B
96F9 30 08 BMI Q703
96FB A9 80 LDA #&80
96FD 19 0C 11 ORA &110C,Y
9700 99 0C 11 STA &110C,Y
.Q703
9703 B9 09 11 LDA &1109,Y
9706 99 14 11 STA &1114,Y
9709 B9 0B 11 LDA &110B,Y
970C 99 15 11 STA &1115,Y
970F B9 0D 11 LDA &110D,Y
9712 20 5F A4 JSR R45F ;extract b5,b4 of A
9715 99 16 11 STA &1116,Y
.Q718
9718 A5 CF LDA &CF ;get current volume
971A 99 1F 11 STA &111F,Y
971D 98 TYA
971E 20 66 A4 JSR R466 ;shift A right 5 places
9721 48 PHA
9722 A8 TAY
9723 88 DEY
9724 20 1A 85 JSR P51A ;save drive parameters of open file
9727 68 PLA
9728 09 10 ORA #&10
972A 60 RTS
.Q72B
972B A9 20 LDA #&20
972D 99 17 11 STA &1117,Y
9730 D0 E6 BNE Q718
.Q732 ;Find unused file handle
9732 AD C3 10 LDA &10C3
9735 A2 04 LDX #&04
.Q737
9737 0A ASL A
9738 90 04 BCC Q73E
973A CA DEX
973B 10 FA BPL Q737
973D 60 RTS
.Q73E
973E BD 4E 97 LDA &974E,X
9741 8D C5 10 STA &10C5
9744 A9 04 LDA #&04
.Q746
9746 0A ASL A
9747 CA DEX
9748 10 FC BPL Q746
974A 8D C4 10 STA &10C4
974D 60 RTS
974E EQUB &A0
974F EQUB &80
9750 EQUB &60
9751 EQUB &40
9752 EQUB &20
.Q753 ;Compare filename at XY+A with open filenames
9753 86 B0 STX &B0
9755 84 B1 STY &B1
9757 85 B2 STA &B2
9759 AD C3 10 LDA &10C3
975C 29 F8 AND #&F8
975E 85 B5 STA &B5
9760 A2 20 LDX #&20
.Q762
9762 86 B4 STX &B4
9764 06 B5 ASL &B5
9766 B0 0C BCS Q774
9768 F0 08 BEQ Q772
.Q76A
976A A5 B4 LDA &B4
976C 18 CLC
976D 69 20 ADC #&20
976F AA TAX
9770 90 F0 BCC Q762
.Q772
9772 18 CLC
9773 60 RTS
.Q774
9774 BD 1F 11 LDA &111F,X
9777 45 CF EOR &CF
9779 D0 EF BNE Q76A
977B A9 08 LDA #&08
977D 85 B3 STA &B3
977F A4 B2 LDY &B2
.Q781
9781 B1 B0 LDA (&B0),Y
9783 5D 00 11 EOR &1100,X
9786 29 7F AND #&7F
9788 D0 E0 BNE Q76A
978A C8 INY
978B E8 INX
978C E8 INX
978D C6 B3 DEC &B3
978F D0 F0 BNE Q781
9791 A4 B4 LDY &B4
9793 60 RTS
;OSARGS
9794 C0 00 CPY #&00 ;file handle in Y; if Y = 0
9796 F0 11 BEQ Q7A9 ;then perform Y = 0 functions
9798 20 00 A3 JSR R300 ;else save AXY
979B C9 FF CMP #&FF ;if A=&FF
979D F0 3B BEQ Q7DA ;then ensure file up-to-date on disc
#if defined _DFSFIX
979F C9 04 CMP #&04 ;else if A>=4
97A1 B0 17 BCS Q7BA ;then return
97A3 4A LSR A ;else place bit 0 of A in carry flag
.Q7A4
97A4 90 40 BCC Q7E6 ;if A=0 or A=2 then return PTR or EXT
97A6 4C 83 BF JMP SF83 ;else A=1 set PTR or A=3 set EXT
#else
979F C9 03 CMP #&03 ;else if A>=3
97A1 B0 17 BCS Q7BA ;then return
97A3 4A LSR A ;else place bit 0 of A in carry flag
97A4 90 40 BCC Q7E6 ;if A=0 or A=2 then return PTR or EXT
97A6 4C 06 98 JMP Q806 ;else A=1 set PTR
#endif
.Q7A9 ;OSARGS Y=0
97A9 20 29 A3 JSR R329 ;save XY
97AC A8 TAY ;A=call number, transfer to Y
97AD C8 INY ;convert &FF,0,1 to 0..2
97AE C0 03 CPY #&03 ;if call number was &02..&FE
97B0 B0 08 BCS Q7BA ;then return
97B2 B9 56 A8 LDA &A856,Y ;else get action address high byte
97B5 48 PHA ;save on stack
97B6 B9 53 A8 LDA &A853,Y ;get action address low byte
97B9 48 PHA ;save on stack
.Q7BA
97BA 60 RTS ;jump to action address.
;OSARGS A=0, Y=0 return filing system number
97BB A9 04 LDA #&04 ;a=4 for Disc Filing System
97BD 60 RTS
;OSARGS A=1, Y=0 read command line tail
97BE A9 FF LDA #&FF ;command line is always in I/O processor
97C0 95 02 STA &02,X ;so return a host address, &FFFFxxxx
97C2 95 03 STA &03,X
97C4 AD D9 10 LDA &10D9 ;copy address of command line arguments
97C7 95 00 STA &00,X ;from workspace where stored by OSFSC 2..4
97C9 AD DA 10 LDA &10DA ;to user's OSARGS block
97CC 95 01 STA &01,X
97CE A9 00 LDA #&00 ;return A=0
97D0 60 RTS
.Q7D1 ;OSARGS A=&FF, Y=0
97D1 AD C3 10 LDA &10C3 ;Ensure all files up-to-date on disc (flush)
97D4 48 PHA ;save channel open flags
97D5 20 D6 95 JSR Q5D6 ;close all files (returns Z=1)
97D8 F0 07 BEQ Q7E1 ;branch (always)
.Q7DA ;OSARGS A=&FF, Y>0 ensure file up-to-date
97DA AD C3 10 LDA &10C3 ;Ensure file up-to-date on disc (flush)
97DD 48 PHA ;save channel open flags
97DE 20 C8 95 JSR Q5C8 ;close a file/all files
.Q7E1
97E1 68 PLA ;restore channel open flags.
97E2 8D C3 10 STA &10C3
97E5 60 RTS
.Q7E6 ;OSARGS A=0/2, Y>0 return PTR/EXT
97E6 20 00 A3 JSR R300 ;save AXY
97E9 20 A7 98 JSR Q8A7 ;ensure file handle valid and open
97EC 0A ASL A ;A=0 or 1, multiply by 4
97ED 0A ASL A ;A=0 offset of PTR, A=4 offset of EXT
97EE 6D C5 10 ADC &10C5 ;add offset to channel workspace pointer
97F1 A8 TAY ;transfer to Y as index
97F2 B9 10 11 LDA &1110,Y ;copy PTR or EXT
97F5 95 00 STA &00,X ;to 3 LSBs of user's OSARGS block
97F7 B9 11 11 LDA &1111,Y
97FA 95 01 STA &01,X
97FC B9 12 11 LDA &1112,Y
97FF 95 02 STA &02,X
9801 A9 00 LDA #&00 ;clear MSB of user's OSARGS block
9803 95 03 STA &03,X ;PTR <= EXT < 16 MiB
9805 60 RTS
.Q806 ;OSARGS A=1, Y>0 set PTR
9806 20 00 A3 JSR R300 ;save AXY
9809 20 A7 98 JSR Q8A7 ;ensure file handle valid and open
980C 38 SEC
980D B9 1C 11 LDA &111C,Y ;get LSB sector address of buffer
9810 F9 0F 11 SBC &110F,Y ;subtract LSB start sector of file
9813 85 B0 STA &B0 ;=offset of buffer from start of file
9815 B9 1D 11 LDA &111D,Y ;get MSB sector address of buffer
9818 F9 0D 11 SBC &110D,Y ;subtract MSB start sector of file
981B 29 03 AND #&03 ;b7..5 of latter = wksp ptr, mask off
981D D5 02 CMP &02,X ;compare b1..0 with 2MSB requested PTR
981F D0 06 BNE Q827 ;if equal
9821 A5 B0 LDA &B0 ;then compare LSB buffer offset with request
9823 D5 01 CMP &01,X
9825 F0 0B BEQ Q832 ;if requested PTR not within current buffer
.Q827
9827 20 97 A5 JSR R597 ;then set current vol/dir from open filename
982A 20 4E 99 JSR Q94E ;ensure buffer up-to-date on disc L6
982D A9 6F LDA #&6F ;b7=0 PTR not in buffer, b4=0 EOF warning clr
982F 20 46 99 JSR Q946 ;clear channel flag bits
.Q832
9832 20 CC 9A JSR QACC ;compare EXT - requested PTR
9835 B0 1C BCS Q853 ;if EXT >= request then just set PTR
9837 B9 14 11 LDA &1114,Y ;else set PTR = EXT
983A 99 10 11 STA &1110,Y
983D B9 15 11 LDA &1115,Y
9840 99 11 11 STA &1111,Y
9843 B9 16 11 LDA &1116,Y
9846 99 12 11 STA &1112,Y
.Q849
9849 A9 00 LDA #&00 ;A = &00 filler byte
984B 20 B0 99 JSR Q9B0 ;write byte to end of file
984E 20 CC 9A JSR QACC ;compare EXT - request
9851 90 F6 BCC Q849 ;loop until last byte is just before new PTR
.Q853
9853 B5 00 LDA &00,X ;copy requested PTR in user's OSARGS block
9855 99 10 11 STA &1110,Y ;to channel pointer
9858 B5 01 LDA &01,X
985A 99 11 11 STA &1111,Y
985D B5 02 LDA &02,X
985F 99 12 11 STA &1112,Y
9862 60 RTS
.Q863 ;Validate workspace offset
9863 48 PHA ;save A
9864 8E C9 10 STX &10C9 ;save X in workspace
9867 98 TYA ;transfer workspace offset to A
9868 29 E0 AND #&E0 ;mask bits 7..5, offset = 0..7 * &20
986A 8D C5 10 STA &10C5 ;save channel workspace pointer
986D F0 11 BEQ Q880 ;if offset = 0 (i.e. channel &10) return C=1
986F 4A LSR A ;else shift right five times, divide by 32
9870 4A LSR A ;to produce an offset 1..7
9871 4A LSR A ;corresponding to channels &11..17
9872 4A LSR A
9873 4A LSR A
9874 A8 TAY ;transfer to Y for use as index
9875 B9 8A 98 LDA &988A,Y ;get channel open bit mask from table
9878 AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
987B 2C C3 10 BIT &10C3 ;if channel's open bit in flag byte = 1
987E D0 03 BNE Q883 ;then return C=0
.Q880
9880 68 PLA ;else return C=1
9881 38 SEC
9882 60 RTS
.Q883
9883 68 PLA
9884 18 CLC
9885 60 RTS
;Table of channel workspace pointers for file handles &11..15
9886 EQUB &20
9887 EQUB &40
9888 EQUB &60
9889 EQUB &80
988A EQUB &A0
;Table of channel open bit masks for file handles &11..18
988B EQUB &80
988C EQUB &40
988D EQUB &20
988E EQUB &10
988F EQUB &08
9890 EQUB &04
9891 EQUB &02
9892 EQUB &01
.Q893
9893 48 PHA ;Convert file handle to channel pointer
9894 98 TYA ;returns C=1 if not in &10..17
9895 C9 10 CMP #&10
9897 90 04 BCC Q89D
9899 C9 18 CMP #&18
989B 90 02 BCC Q89F
.Q89D
989D A9 08 LDA #&08
.Q89F
989F 0A ASL A
98A0 0A ASL A
98A1 0A ASL A
98A2 0A ASL A
98A3 0A ASL A
98A4 A8 TAY
98A5 68 PLA
98A6 60 RTS
.Q8A7 ;Ensure file handle valid and open
98A7 48 PHA
98A8 98 TYA
98A9 38 SEC
98AA E9 11 SBC #&11 ;subtract lowest valid handle; if result <0
98AC 90 18 BCC Q8C6 ;then raise "Channel" error
98AE C9 05 CMP #&05 ;else if result >= 5
98B0 B0 14 BCS Q8C6 ;then raise "Channel" error
98B2 A8 TAY ;else transfer to Y as offset 0..4
98B3 B9 86 98 LDA &9886,Y ;get channel workspace pointer from table
98B6 8D C5 10 STA &10C5 ;save in temporary location
98B9 B9 8B 98 LDA &988B,Y ;get channel open bit mask from table
98BC AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
98BF 2C C3 10 BIT &10C3 ;if channel's open bit in flag byte = 0
98C2 F0 02 BEQ Q8C6 ;then raise "Channel" error
98C4 68 PLA
98C5 60 RTS
.Q8C6
98C6 20 62 A3 JSR R362 ;Raise "Channel" error
98C9 EQUB &DE
98CA EQUS "Channel"
98D1 EQUB &00
.Q8D2
98D2 20 62 A3 JSR R362
98D5 EQUB &DF
98D6 EQUS "EOF"
98D9 EQUB &00
.Q8DA ;OSBGET
98DA 8E 28 10 STX &1028
98DD 8C 29 10 STY &1029
98E0 20 A7 98 JSR Q8A7 ;ensure file handle valid and open
98E3 98 TYA
98E4 20 B4 9A JSR QAB4 ;compare PTR - EXT
98E7 D0 11 BNE Q8FA ;if at EOF
98E9 B9 17 11 LDA &1117,Y ;then test EOF warning flag b4
98EC 29 10 AND #&10
98EE D0 E2 BNE Q8D2 ;if set then raise "EOF" error
98F0 A9 10 LDA #&10 ;else set EOF warning flag b4=1
98F2 20 3F 99 JSR Q93F ;set channel flag bits (A = OR mask)
98F5 A9 FE LDA #&FE ;return A=&FE, "file end"
98F7 38 SEC ;return C=1 indicating end-of-file
98F8 B0 21 BCS Q91B ;restore XY and exit
.Q8FA
98FA B9 17 11 LDA &1117,Y
98FD 30 0A BMI Q909
98FF 20 97 A5 JSR R597 ;set current vol/dir from open filename
9902 20 51 99 JSR Q951 ;ensure buffer up-to-date on disc L6
9905 38 SEC ;c=1 read buffer from disc
9906 20 59 99 JSR Q959 ;read/write sector buffer L6
.Q909
9909 B9 10 11 LDA &1110,Y
990C 85 BC STA &BC
990E B9 13 11 LDA &1113,Y
9911 85 BD STA &BD
9913 20 9D 9A JSR QA9D
9916 A0 00 LDY #&00
9918 B1 BC LDA (&BC),Y
991A 18 CLC
.Q91B
991B AE 28 10 LDX &1028
991E AC 29 10 LDY &1029
9921 48 PHA
9922 68 PLA
9923 60 RTS
.Q924 ;Set buffer sector address from PTR
9924 18 CLC
9925 B9 0F 11 LDA &110F,Y ;get LSB start sector of open file
9928 79 11 11 ADC &1111,Y ;add 2MSB of PTR
992B 85 C5 STA &C5 ;store LSB sector address
992D 99 1C 11 STA &111C,Y ;store LSB sector address of buffer
9930 B9 0D 11 LDA &110D,Y ;get top bits exec/length/load/start sector
9933 29 03 AND #&03 ;extract MSB start sector
9935 79 12 11 ADC &1112,Y ;add MSB of PTR
9938 85 C4 STA &C4 ;store MSB sector address
993A 99 1D 11 STA &111D,Y ;store MSB sector address of buffer
993D A9 80 LDA #&80 ;set buffer-contains-PTR channel flag:
.Q93F
993F 19 17 11 ORA &1117,Y ;Set channel flag bits (A = OR mask)
9942 D0 05 BNE Q949
.Q944
9944 A9 7F LDA #&7F ;Clear buffer-contains-PTR channel flag:
.Q946
9946 39 17 11 AND &1117,Y ;Clear channel flag bits (A = AND mask)
.Q949
9949 99 17 11 STA &1117,Y
994C 18 CLC
994D 60 RTS
.Q94E
994E 20 00 A3 JSR R300 ;save AXY
.Q951 ;Ensure buffer up-to-date on disc L6
9951 B9 17 11 LDA &1117,Y ;test b6 of channel flag
9954 29 40 AND #&40
9956 F0 46 BEQ Q99E ;if buffer not changed then return
9958 18 CLC ;c=0 write buffer to disc:
.Q959 ;Read/write sector buffer L6
9959 08 PHP
995A AD C5 10 LDA &10C5 ;get channel workspace pointer
995D 20 66 A4 JSR R466 ;shift A right 5 places
9960 A8 TAY
9961 88 DEY ;Y=0..4 for handles &11..15
9962 20 FC 84 JSR P4FC ;copy channel's drive parameters to &10E0..5
9965 20 D6 A7 JSR R7D6 ;set up for current drive
9968 AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
996B B9 13 11 LDA &1113,Y ;get MSB address of buffer in shared wksp
996E 85 BF STA &BF
9970 20 28 92 JSR Q228 ;set high word of buffer address = &FFFF
9973 A9 00 LDA #&00 ;clear LSB buffer address
9975 85 BE STA &BE
9977 85 C2 STA &C2
9979 A9 01 LDA #&01 ;256 bytes to transfer
997B 85 C3 STA &C3
997D 28 PLP
997E B0 15 BCS Q995 ;if C was 0 on entry then read buffer
9980 B9 1C 11 LDA &111C,Y ;else copy channel's sector buffer address
9983 85 C5 STA &C5 ;to &C5,4 (big-endian)
9985 B9 1D 11 LDA &111D,Y
9988 85 C4 STA &C4
998A 20 09 90 JSR Q009 ;write ordinary file L5
998D AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
9990 A9 BF LDA #&BF ;b6=0 buffer not changed
9992 4C 46 99 JMP Q946 ;clear channel flag bits and exit
.Q995 ;Read channel buffer from disc L6
9995 20 24 99 JSR Q924 ;set buffer sector address from PTR
9998 20 0F 90 JSR Q00F ;read ordinary file L5
999B AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
.Q99E
999E 60 RTS
.Q99F
999F 4C ED 9B JMP QBED ;raise "File locked" error.
.Q9A2 ;Raise "File read only" error.
99A2 20 5A A3 JSR R35A
99A5 EQUB &C1
99A6 EQUS "read only"
99AF EQUB &00
.Q9B0
99B0 20 00 A3 JSR R300 ;save AXY
99B3 4C C2 99 JMP Q9C2
.Q9B6 ;OSBPUT
99B6 8D 27 10 STA &1027
99B9 8E 28 10 STX &1028
99BC 8C 29 10 STY &1029
99BF 20 A7 98 JSR Q8A7 ;ensure file handle valid and open
.Q9C2
99C2 48 PHA
99C3 B9 0C 11 LDA &110C,Y ;test channel read-only bit
99C6 30 DA BMI Q9A2 ;if b7=1 then raise "File read only" error
99C8 B9 0E 11 LDA &110E,Y ;else test file locked bit
99CB 30 D2 BMI Q99F ;if b7=1 then raise "File locked" error
99CD 20 97 A5 JSR R597 ;else set current vol/dir from open filename
99D0 98 TYA ;a=y = channel workspace pointer
99D1 18 CLC ;add 4 to point A to allocated length not EXT
99D2 69 04 ADC #&04
99D4 20 B4 9A JSR QAB4 ;compare PTR - allocated length
99D7 D0 6A BNE QA43 ;if within allocation then write
99D9 20 93 95 JSR Q593 ;else ensure open file still on current volume
99DC AE C7 10 LDX &10C7 ;get offset of file in catalogue
99DF 38 SEC
99E0 BD 07 0F LDA &0F07,X ;get LSB start LBA of previous file in cat
99E3 FD 0F 0F SBC &0F0F,X ;subtract LSB start LBA of open file
99E6 48 PHA ;save LSB maximum available allocation
99E7 BD 06 0F LDA &0F06,X ;get MSB start LBA of previous file in cat
99EA FD 0E 0F SBC &0F0E,X ;subtract MSB start LBA of open file
99ED 29 03 AND #&03 ;extract b1,b0
99EF 8D C6 10 STA &10C6 ;store MSB maximum available allocation
99F2 20 F0 8F JSR PFF0 ;pack b17,16 of length into catalogue entry
99F5 AD C6 10 LDA &10C6 ;get MSB maximum available allocation
99F8 D9 1A 11 CMP &111A,Y ;compare MSB length of file per workspace
99FB D0 2E BNE QA2B ;if not equal then extend file
99FD 68 PLA ;else restore LSB maximum available allocation
99FE D9 19 11 CMP &1119,Y ;compare 2MSB length of file per workspace
9A01 D0 29 BNE QA2C ;if not equal then extend file
9A03 84 B4 STY &B4 ;else save workspace pointer
9A05 20 0C A8 JSR R80C ;call OSBYTE &C7 = read/write *SPOOL handle
9A08 8A TXA ;if *SPOOL not in use
9A09 F0 0A BEQ QA15 ;then close file and raise "Can't extend"
9A0B BD 75 98 LDA &9875,X ;else get workspace pointer to *SPOOL file
9A0E C5 B4 CMP &B4 ;compare with workspace pointer to this file
9A10 D0 03 BNE QA15 ;if equal
9A12 20 FB A7 JSR R7FB ;then disable *SPOOL output.
.QA15
9A15 A4 B4 LDY &B4 ;get workspace pointer
9A17 20 E2 95 JSR Q5E2 ;close file
9A1A 20 62 A3 JSR R362 ;raise "Can't extend" error.
9A1D EQUB &BF
9A1E EQUS "Can't extend"
9A2A EQUB &00
;extend file
.QA2B
9A2B 68 PLA ;restore LSB maximum allocation
.QA2C
9A2C 9D 0D 0F STA &0F0D,X ;store 2MSB file length in catalogue
9A2F 99 19 11 STA &1119,Y ;store 2MSB file length in workspace
9A32 AD C6 10 LDA &10C6 ;get MSB maximum allocation
9A35 99 1A 11 STA &111A,Y ;store MSB file length in workspace
9A38 A9 00 LDA #&00 ;clear LSB file length in catalogue
9A3A 9D 0C 0F STA &0F0C,X
9A3D 20 81 92 JSR Q281 ;write volume catalogue
9A40 AC C5 10 LDY &10C5 ;put channel workspace pointer in Y
.QA43 ;write byte to file
9A43 B9 17 11 LDA &1117,Y ;test channel flags
9A46 30 17 BMI QA5F ;if b7=1 buffer-contains-PTR then write byte
9A48 20 51 99 JSR Q951 ;else ensure buffer up-to-date on disc L6
9A4B B9 14 11 LDA &1114,Y ;does EXT equal a whole number of sectors?
9A4E D0 0B BNE QA5B ;if not then read buffer from disc
9A50 98 TYA ;else a=y = channel workspace pointer
9A51 20 B4 9A JSR QAB4 ;compare PTR - EXT
9A54 D0 05 BNE QA5B ;if not at EOF then read buffer from disc
9A56 20 24 99 JSR Q924 ;else set buffer sector address from PTR
9A59 D0 04 BNE QA5F ;branch (always)
.QA5B
9A5B 38 SEC ;c=1 read buffer from disc
9A5C 20 59 99 JSR Q959 ;read/write sector buffer L6
.QA5F
9A5F B9 10 11 LDA &1110,Y
9A62 85 BC STA &BC
9A64 B9 13 11 LDA &1113,Y
9A67 85 BD STA &BD
9A69 20 9D 9A JSR QA9D
9A6C 68 PLA
9A6D A2 00 LDX #&00
9A6F 81 BC STA (&BC,X)
9A71 A9 40 LDA #&40
9A73 20 3F 99 JSR Q93F
9A76 98 TYA ;a=y = channel workspace pointer
9A77 20 B4 9A JSR QAB4 ;compare PTR - EXT
9A7A 90 17 BCC QA93 ;if at EOF (i.e. pointer >= EXT)
9A7C A9 20 LDA #&20 ;then b5=1, EXT has changed
9A7E 20 3F 99 JSR Q93F ;set channel flag bits
9A81 B9 10 11 LDA &1110,Y ;copy EXT = PTR
9A84 99 14 11 STA &1114,Y
9A87 B9 11 11 LDA &1111,Y
9A8A 99 15 11 STA &1115,Y
9A8D B9 12 11 LDA &1112,Y
9A90 99 16 11 STA &1116,Y
.QA93
9A93 AD 27 10 LDA &1027
9A96 AE 28 10 LDX &1028
9A99 AC 29 10 LDY &1029
9A9C 60 RTS
.QA9D
9A9D 98 TYA
9A9E AA TAX
9A9F A5 BC LDA &BC
9AA1 9D 10 11 STA &1110,X
9AA4 FE 10 11 INC &1110,X
9AA7 D0 22 BNE QACB
9AA9 FE 11 11 INC &1111,X
9AAC D0 03 BNE QAB1
9AAE FE 12 11 INC &1112,X
.QAB1
9AB1 4C 44 99 JMP Q944
.QAB4 ;Compare PTR - EXT (A=Y), - allocation (A=Y+4)
9AB4 AA TAX ;return C=1 iff at/past EOF or allocation
9AB5 B9 12 11 LDA &1112,Y ;return Z=1 iff at EOF or equal to allocation
9AB8 DD 16 11 CMP &1116,X
9ABB D0 0E BNE QACB
9ABD B9 11 11 LDA &1111,Y
9AC0 DD 15 11 CMP &1115,X
9AC3 D0 06 BNE QACB
9AC5 B9 10 11 LDA &1110,Y
9AC8 DD 14 11 CMP &1114,X
.QACB
9ACB 60 RTS
.QACC
9ACC B9 14 11 LDA &1114,Y
9ACF D5 00 CMP &00,X
9AD1 B9 15 11 LDA &1115,Y
9AD4 F5 01 SBC &01,X
9AD6 B9 16 11 LDA &1116,Y
9AD9 F5 02 SBC &02,X
9ADB 60 RTS
;OSFILE
9ADC 20 29 A3 JSR R329 ;save XY
9ADF 48 PHA ;push A
9AE0 20 2F 89 JSR P92F ;disallow wildcard characters in filename
9AE3 86 B0 STX &B0 ;set up pointer from XY
9AE5 8E DB 10 STX &10DB
9AE8 84 B1 STY &B1
9AEA 8C DC 10 STY &10DC
9AED A2 00 LDX #&00
9AEF A0 00 LDY #&00
9AF1 20 DB 87 JSR P7DB ;copy word at pointer to &BC,D
.QAF4
9AF4 20 CB 87 JSR P7CB ;copy next four dwords to &BE..C5 (low words)
9AF7 C0 12 CPY #&12 ;&106F..76 (high words)
9AF9 D0 F9 BNE QAF4
9AFB 68 PLA ;transfer call number to X
9AFC AA TAX
#if defined _DFSFIX
9AFD 20 64 BF JSR SF64 ;handle OSFILE calls 7,9,11 or validate index
#else
9AFD E8 INX ;increment for use as index
9AFE E0 08 CPX #&08 ;was call number &FF or 0..6?
#endif
9B00 B0 08 BCS QB0A ;if not then exit
9B02 BD 61 A8 LDA &A861,X ;else get action address high byte
9B05 48 PHA ;save on stack
9B06 BD 59 A8 LDA &A859,X ;get action address low byte
9B09 48 PHA ;save on stack
.QB0A
9B0A 60 RTS ;jump to action address
;OSFILE 0 = save file
9B0B 20 F0 90 JSR Q0F0 ;create file from OSFILE block
9B0E 20 22 9C JSR QC22 ;set up pointer to user's OSFILE block
9B11 20 06 8A JSR PA06 ;return catalogue information to OSFILE block
9B14 4C 09 90 JMP Q009 ;write ordinary file L5
;OSFILE 1 = write catalogue information
9B17 20 E3 9B JSR QBE3
9B1A 20 8B 9B JSR QB8B
9B1D 20 A7 9B JSR QBA7
9B20 50 16 BVC QB38
;OSFILE 2 = write load address
9B22 20 E3 9B JSR QBE3
9B25 20 8B 9B JSR QB8B
9B28 50 11 BVC QB3B
;OSFILE 3 = write execution address
9B2A 20 E3 9B JSR QBE3
9B2D 20 A7 9B JSR QBA7
9B30 50 09 BVC QB3B
;OSFILE 4 = write file attributes
9B32 20 0E 9C JSR QC0E
9B35 20 FB 9B JSR QBFB ;ensure file not open (mutex)
.QB38
9B38 20 CA 9B JSR QBCA
.QB3B
9B3B 20 96 90 JSR Q096
9B3E A9 01 LDA #&01
9B40 60 RTS
;OSFILE 5 = read catalogue information
9B41 20 0E 9C JSR QC0E
9B44 20 06 8A JSR PA06 ;return catalogue information to OSFILE block
9B47 A9 01 LDA #&01
9B49 60 RTS
;OSFILE 6 = delete file
9B4A 20 E3 9B JSR QBE3
9B4D 20 06 8A JSR PA06 ;return catalogue information to OSFILE block
9B50 20 9E 89 JSR P99E ;delete catalogue entry
9B53 4C 3B 9B JMP QB3B
;OSFILE &FF = load file
9B56 20 3B 89 JSR P93B ;ensure file matching argument in catalogue
9B59 20 22 9C JSR QC22 ;set up pointer to user's OSFILE block
9B5C 20 06 8A JSR PA06 ;return catalogue information to OSFILE block
.QB5F ;Load file into memory
9B5F 84 BC STY &BC
9B61 A2 00 LDX #&00
9B63 A5 C0 LDA &C0 ;test offset 6, LSB exec from OSFILE block
9B65 D0 06 BNE QB6D ;if non-zero, use load address in catalogue
9B67 C8 INY ;else skip first two bytes of catalogue entry
9B68 C8 INY
9B69 A2 02 LDX #&02 ;skip over user-supplied load address in zp
9B6B D0 08 BNE QB75 ;branch (always)
.QB6D
9B6D B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
9B70 85 C4 STA &C4
9B72 20 19 92 JSR Q219 ;expand 18-bit load address to 32-bit
.QB75
9B75 B9 08 0F LDA &0F08,Y ;copy load/exec/length/start from catalogue
9B78 95 BE STA &BE,X ;into low words of OSFILE block
9B7A C8 INY ;(our copy, gave user theirs at &9B5C)
9B7B E8 INX
9B7C E0 08 CPX #&08 ;loop until 8 or 6 bytes copied, 0..7/2..7
9B7E D0 F5 BNE QB75
9B80 20 35 92 JSR Q235 ;expand 18-bit exec address to 32-bit
9B83 A4 BC LDY &BC
9B85 20 BB 89 JSR P9BB ;print *INFO line if verbose
9B88 4C 0F 90 JMP Q00F ;read ordinary file L5 and exit
.QB8B
9B8B 20 00 A3 JSR R300 ;save AXY
9B8E A0 02 LDY #&02
9B90 B1 B0 LDA (&B0),Y
9B92 9D 08 0F STA &0F08,X
9B95 C8 INY
9B96 B1 B0 LDA (&B0),Y
9B98 9D 09 0F STA &0F09,X
9B9B C8 INY
9B9C B1 B0 LDA (&B0),Y
9B9E 0A ASL A
9B9F 0A ASL A
9BA0 5D 0E 0F EOR &0F0E,X
9BA3 29 0C AND #&0C
9BA5 10 1B BPL QBC2
.QBA7
9BA7 20 00 A3 JSR R300 ;save AXY
9BAA A0 06 LDY #&06
9BAC B1 B0 LDA (&B0),Y
9BAE 9D 0A 0F STA &0F0A,X
9BB1 C8 INY
9BB2 B1 B0 LDA (&B0),Y
9BB4 9D 0B 0F STA &0F0B,X
9BB7 C8 INY
9BB8 B1 B0 LDA (&B0),Y
9BBA 6A ROR A
9BBB 6A ROR A
9BBC 6A ROR A
9BBD 5D 0E 0F EOR &0F0E,X
9BC0 29 C0 AND #&C0
.QBC2
9BC2 5D 0E 0F EOR &0F0E,X
9BC5 9D 0E 0F STA &0F0E,X
9BC8 B8 CLV
9BC9 60 RTS
.QBCA
9BCA 20 00 A3 JSR R300 ;save AXY
9BCD A0 0E LDY #&0E
9BCF B1 B0 LDA (&B0),Y
9BD1 29 0A AND #&0A
9BD3 F0 02 BEQ QBD7
9BD5 A9 80 LDA #&80
.QBD7
9BD7 5D 0F 0E EOR &0E0F,X
9BDA 29 80 AND #&80
9BDC 5D 0F 0E EOR &0E0F,X
9BDF 9D 0F 0E STA &0E0F,X
9BE2 60 RTS
.QBE3
9BE3 20 18 9C JSR QC18
9BE6 90 2B BCC QC13
.QBE8 ;Ensure file not locked
9BE8 B9 0F 0E LDA &0E0F,Y ;if directory character b7=1
9BEB 10 2A BPL QC17
.QBED
9BED 20 5A A3 JSR R35A ;then raise "File locked" error.
9BF0 EQUB &C3
9BF1 EQUS "locked"
9BF7 EQUB &00
.QBF8 ;Ensure file not locked or open (mutex)
9BF8 20 E8 9B JSR QBE8 ;ensure file not locked
.QBFB ;Ensure file not open (mutex)
9BFB 20 00 A3 JSR R300 ;save AXY
9BFE 98 TYA ;save catalogue pointer
9BFF 48 PHA
9C00 A2 08 LDX #&08 ;point XY to filename in catalogue, &0E08
9C02 A0 0E LDY #&0E
9C04 68 PLA
9C05 20 53 97 JSR Q753 ;compare filename at XY+A with open filenames
9C08 90 03 BCC QC0D ;if unequal then return
9C0A 4C 66 96 JMP Q666 ;else raise "File open" error.
.QC0D
9C0D 60 RTS
.QC0E
9C0E 20 18 9C JSR QC18
9C11 B0 04 BCS QC17
.QC13
9C13 68 PLA
9C14 68 PLA
9C15 A9 00 LDA #&00
.QC17
9C17 60 RTS
.QC18
9C18 20 EB 87 JSR P7EB ;set current file from argument pointer
9C1B 20 63 89 JSR P963 ;search for file in catalogue
9C1E 90 0C BCC QC2C
9C20 98 TYA
9C21 AA TAX
.QC22 ;Set up pointer to user's OSFILE block
9C22 AD DB 10 LDA &10DB
9C25 85 B0 STA &B0
9C27 AD DC 10 LDA &10DC
9C2A 85 B1 STA &B1
.QC2C
9C2C 60 RTS
;OSGBPB
9C2D C9 09 CMP #&09
9C2F B0 FB BCS QC2C ;if call number >=9 then return
9C31 20 00 A3 JSR R300 ;else save AXY
9C34 20 F3 A2 JSR R2F3 ;have A=0 returned on exit
9C37 8E 7F 10 STX &107F ;save OSGBPB block pointer in workspace
9C3A 8C 80 10 STY &1080
9C3D A8 TAY ;transfer call number to Y for use as index
9C3E 20 47 9C JSR QC47 ;execute OSGBPB call
9C41 08 PHP
9C42 20 45 93 JSR Q345 ;release Tube if present
9C45 28 PLP
9C46 60 RTS
.QC47
9C47 B9 69 A8 LDA &A869,Y ;get low byte of action address from table
9C4A 8D D7 10 STA &10D7
9C4D B9 72 A8 LDA &A872,Y ;get high byte of action address from table
9C50 8D D8 10 STA &10D8
9C53 B9 7B A8 LDA &A87B,Y ;get microcode byte from table
9C56 4A LSR A ;push bit 0 as C
9C57 08 PHP
9C58 4A LSR A ;push bit 1 as C
9C59 08 PHP
9C5A 8D 81 10 STA &1081 ;store Tube service call number as bits 0..5
9C5D 20 0A 9E JSR QE0A ;set up pointer to user's OSGBPB block
9C60 A0 0C LDY #&0C ;13 bytes to copy, &0C..&00:
.QC62
9C62 B1 B4 LDA (&B4),Y ;copy user's OSGBPB block
9C64 99 60 10 STA &1060,Y ;to workspace
9C67 88 DEY ;loop until 13 bytes copied
9C68 10 F8 BPL QC62
9C6A AD 63 10 LDA &1063 ;and high bytes of address
9C6D 2D 64 10 AND &1064 ;a=&FF if address is in the host
9C70 0D D6 10 ORA &10D6 ;a=&FF if Tube absent (&10D6=NOT MOS flag!)
9C73 18 CLC
9C74 69 01 ADC #&01 ;set A=0, C=1 if transferring to/from host
9C76 F0 06 BEQ QC7E ;if A>0
9C78 20 2E 93 JSR Q32E ;then claim Tube
9C7B 18 CLC
9C7C A9 FF LDA #&FF ;and set A=&FF, C=0, transferring to/from Tube
.QC7E
9C7E 8D 83 10 STA &1083 ;set Tube transfer flag
9C81 AD 81 10 LDA &1081 ;set A=0 if writing user mem, A=1 if reading
9C84 B0 07 BCS QC8D ;if transferring to/from Tube
9C86 A2 61 LDX #&61 ;then point XY to OSGBPB data address
9C88 A0 10 LDY #&10
9C8A 20 06 04 JSR &0406 ;call Tube service to open Tube data channel
.QC8D
9C8D 28 PLP ;set C=microcode b1
9C8E B0 04 BCS QC94 ;if reading/writing data then transfer it
9C90 28 PLP ;else C=microcode b0 (=0), pop off stack
.QC91
9C91 6C D7 10 JMP (&10D7) ;and jump to action address.
.QC94
9C94 A2 03 LDX #&03 ;4 bytes to copy, 3..0:
.QC96
9C96 BD 69 10 LDA &1069,X ;copy OSGBPB pointer field
9C99 95 B6 STA &B6,X ;to zero page
9C9B CA DEX
9C9C 10 F8 BPL QC96
9C9E A2 B6 LDX #&B6 ;point X to pointer in zero page
9CA0 AC 60 10 LDY &1060 ;set Y=channel number
9CA3 A9 00 LDA #&00 ;set A=0, read PTR not EXT
9CA5 28 PLP ;set C=microcode b0
9CA6 B0 03 BCS QCAB ;if C=0
#if defined _DFSFIX
9CA8 20 BB BF JSR SFBB ;then call OSARGS 1,Y set PTR.
#else
9CA8 20 06 98 JSR Q806 ;then call OSARGS 1,Y set PTR.
#endif
.QCAB
9CAB 20 E6 97 JSR Q7E6 ;call OSARGS 0,Y return PTR
9CAE A2 03 LDX #&03 ;4 bytes to copy, 3..0:
.QCB0
9CB0 B5 B6 LDA &B6,X ;copy pointer in zero page
9CB2 9D 69 10 STA &1069,X ;to OSGBPB pointer field
9CB5 CA DEX
9CB6 10 F8 BPL QCB0
.QCB8
9CB8 20 FC 9D JSR QDFC ;invert OSGBPB length field
9CBB 30 0D BMI QCCA ;and branch into loop (always)
.QCBD
9CBD AC 60 10 LDY &1060 ;set Y = channel number
9CC0 20 91 9C JSR QC91 ;transfer byte / element
9CC3 B0 0D BCS QCD2 ;if attempted read past EOF then finish
9CC5 A2 09 LDX #&09 ;else set X = &09, point to OSGBPB pointer
9CC7 20 F0 9D JSR QDF0 ;increment pointer
.QCCA
9CCA A2 05 LDX #&05 ;set X = &05, point to OSGBPB length field
9CCC 20 F0 9D JSR QDF0 ;increment OSGBPB length field (inverted)
9CCF D0 EC BNE QCBD ;if not overflowed to zero then loop
9CD1 18 CLC ;else set C = 0, no read past EOF:
.QCD2
9CD2 08 PHP
9CD3 20 FC 9D JSR QDFC ;invert OSGBPB length field
9CD6 A2 05 LDX #&05 ;add one to get two's complement (0 -> 0)
9CD8 20 F0 9D JSR QDF0 ;thus, number of elements not transferred
#if defined _DFSFIX
9CDB 20 C9 BF JSR SFC9 ;set up user pointer and clear EOF warning
9CDE A0 0C LDY #&0C ;13 bytes to copy, offsets 0..&C:
#else
9CDB A0 0C LDY #&0C ;13 bytes to copy, offsets 0..&C:
9CDD 20 0A 9E JSR QE0A ;set up pointer to user's OSGBPB block
#endif
.QCE0
9CE0 B9 60 10 LDA &1060,Y ;copy OSGBPB block back to user memory
9CE3 91 B4 STA (&B4),Y
9CE5 88 DEY
9CE6 10 F8 BPL QCE0
9CE8 28 PLP
.QCE9 ;OSGBPB 0 = no operation
9CE9 60 RTS
;OSGBPB 1 = set pointer and write data
;OSGBPB 2 = write data
9CEA 20 A5 9D JSR QDA5 ;get byte from user memory
9CED 20 B6 99 JSR Q9B6 ;call OSBPUT; write byte to file
9CF0 18 CLC ;return C=0 no end-of-file condition
9CF1 60 RTS
;OSGBPB 3 = set pointer and read data
;OSGBPB 4 = read data
9CF2 20 DA 98 JSR Q8DA ;call OSBGET; read byte from file
9CF5 B0 F2 BCS QCE9 ;if end-of-file reached return C=1
9CF7 4C DC 9D JMP QDDC ;else write data byte to user memory
;OSGBPB 5 = read title, boot option and drive
9CFA 20 FB A4 JSR R4FB ;set current vol/dir = default, set up drive
9CFD 20 92 92 JSR Q292 ;ensure current volume catalogue loaded
9D00 A9 0C LDA #&0C ;write 12 to user memory
9D02 20 DC 9D JSR QDDC ;= length of title
9D05 A0 00 LDY #&00 ;set offset to 0
.QD07
9D07 B9 00 0E LDA &0E00,Y ;get first eight characters of title
9D0A 20 DC 9D JSR QDDC ;write to user memory
9D0D C8 INY
9D0E C0 08 CPY #&08 ;loop until 8 characters written
9D10 D0 F5 BNE QD07
.QD12
9D12 B9 F8 0E LDA &0EF8,Y ;get last four characters from &0F00..3
9D15 20 DC 9D JSR QDDC ;write to user memory (Y = 8..11)
9D18 C8 INY
9D19 C0 0C CPY #&0C ;loop until 4 more characters written
9D1B D0 F5 BNE QD12
9D1D AD 06 0F LDA &0F06 ;get boot option/top bits volume size
9D20 20 67 A4 JSR R467 ;shift A right 4 places
9D23 20 DC 9D JSR QDDC ;write boot option to user memory
9D26 A5 CF LDA &CF ;get current volume (incl. vol letter b6..4)
9D28 4C DC 9D JMP QDDC ;write to user memory and exit
;OSGBPB 6 = read default (CSD) drive and dir
9D2B AD CB 10 LDA &10CB ;get default volume
9D2E 20 B8 9D JSR QDB8 ;write length+drive identifier to user memory
9D31 20 DA 9D JSR QDDA ;write binary 1 to user memory
9D34 AD CA 10 LDA &10CA ;get default directory character
9D37 4C DC 9D JMP QDDC ;write it to user memory and exit
;OSGBPB 7 = read library drive and directory
9D3A AD CD 10 LDA &10CD ;get library volume
9D3D 20 B8 9D JSR QDB8 ;write length+drive identifier to user memory
9D40 20 DA 9D JSR QDDA ;write binary 1 to user memory
9D43 AD CC 10 LDA &10CC ;get library directory character
9D46 4C DC 9D JMP QDDC ;write it to user memory and exit
;OSGBPB 8 = read filenames in default dir
9D49 20 FB A4 JSR R4FB ;set current vol/dir = default, set up drive
9D4C 20 92 92 JSR Q292 ;ensure current volume catalogue loaded
9D4F A9 5C LDA #&5C ;replace action address with &9D5C
9D51 8D D7 10 STA &10D7 ;= return one filename
9D54 A9 9D LDA #&9D
9D56 8D D8 10 STA &10D8
9D59 4C B8 9C JMP QCB8 ;and return requested number of filenames.
;Return one filename (called during OSGBPB 8)
9D5C AC 69 10 LDY &1069 ;set Y = catalogue pointer (0 on first call)
.QD5F
9D5F CC 05 0F CPY &0F05 ;compare with no. files in catalogue
9D62 B0 28 BCS QD8C ;if out of files return C=1, read past EOF
9D64 B9 0F 0E LDA &0E0F,Y ;else get directory character of cat entry
9D67 20 9A A4 JSR R49A ;set C=0 iff character in A is a letter
9D6A 45 CE EOR &CE ;compare with current directory character
9D6C B0 02 BCS QD70 ;if directory character is a letter
9D6E 29 DF AND #&DF ;then ignore case.
.QD70
9D70 29 7F AND #&7F ;mask off attribute bit b7
9D72 F0 05 BEQ QD79 ;if catalogue entry not in current directory
9D74 20 72 A4 JSR R472 ;then add 8 to Y
9D77 D0 E6 BNE QD5F ;and loop (always)
.QD79
9D79 A9 07 LDA #&07 ;else write 7 to user memory
9D7B 20 DC 9D JSR QDDC ;= length of filename
9D7E 85 B0 STA &B0 ;set counter to 7
.QD80
9D80 B9 08 0E LDA &0E08,Y ;get character of leaf name
9D83 20 DC 9D JSR QDDC ;write byte to user memory
9D86 C8 INY ;increment catalogue pointer
9D87 C6 B0 DEC &B0 ;loop until 7 characters transferred
9D89 D0 F5 BNE QD80
9D8B 18 CLC ;c=0, did not run out of filenames:
.QD8C
9D8C 8C 69 10 STY &1069 ;put updated cat ptr in OSGBPB pointer field
9D8F AD 04 0F LDA &0F04 ;return catalogue cycle no. in channel field
9D92 8D 60 10 STA &1060
9D95 60 RTS
.QD96 ;Set up pointer to user I/O memory
9D96 48 PHA
9D97 AD 61 10 LDA &1061
9D9A 85 B8 STA &B8
9D9C AD 62 10 LDA &1062
9D9F 85 B9 STA &B9
9DA1 A2 00 LDX #&00 ;offset = 0 for indexed indirect load/store
9DA3 68 PLA
9DA4 60 RTS
.QDA5 ;Read data byte from user memory
9DA5 2C 83 10 BIT &1083 ;test Tube transfer flag
9DA8 10 06 BPL QDB0 ;if b7=0 then read from I/O memory
9DAA AD E5 FE LDA &FEE5 ;else read from Tube FIFO 3
9DAD 4C EB 9D JMP QDEB ;increment OSGBPB address field
.QDB0
9DB0 20 96 9D JSR QD96 ;set up pointer to user I/O memory
9DB3 A1 B8 LDA (&B8,X) ;read byte from user I/O memory
9DB5 4C EB 9D JMP QDEB ;increment OSGBPB address field
.QDB8 ;Write length+drive identifier to user memory
9DB8 48 PHA
9DB9 A0 01 LDY #&01 ;return Y=1
9DBB 29 F0 AND #&F0 ;unless volume letter is B..H
9DBD F0 01 BEQ QDC0
9DBF C8 INY ;in which case return Y=2
.QDC0
9DC0 98 TYA
9DC1 20 DC 9D JSR QDDC ;write length of drive ID to user memory
9DC4 68 PLA
9DC5 48 PHA
9DC6 29 0F AND #&0F ;extract drive number
9DC8 18 CLC
9DC9 69 30 ADC #&30 ;convert to ASCII digit
9DCB 20 DC 9D JSR QDDC ;write data byte to user memory
9DCE 68 PLA
9DCF 20 67 A4 JSR R467 ;shift A right 4 places
9DD2 F0 40 BEQ QE14 ;if volume letter is A then exit
9DD4 18 CLC
9DD5 69 41 ADC #&41 ;else convert binary to letter A..H
9DD7 4C DC 9D JMP QDDC ;write it to user memory and exit
.QDDA ;Write binary 1 to user memory
9DDA A9 01 LDA #&01
.QDDC ;Write data byte to user memory
9DDC 2C 83 10 BIT &1083 ;test Tube flag
9DDF 10 05 BPL QDE6 ;if Tube not in use then write to I/O memory
9DE1 8D E5 FE STA &FEE5 ;else put byte in Tube FIFO 3
9DE4 30 05 BMI QDEB ;and increment OSGBPB address field (always)
.QDE6
9DE6 20 96 9D JSR QD96 ;set up pointer to user I/O memory
9DE9 81 B8 STA (&B8,X) ;store byte at pointer:
.QDEB ;Increment OSGBPB address field
9DEB 20 00 A3 JSR R300 ;save AXY
9DEE A2 01 LDX #&01 ;set X = &01, point to OSGBPB data address:
.QDF0
9DF0 A0 04 LDY #&04 ;Increment OSGBPB field
.QDF2
9DF2 FE 60 10 INC &1060,X
9DF5 D0 04 BNE QDFB
9DF7 E8 INX
9DF8 88 DEY
9DF9 D0 F7 BNE QDF2
.QDFB
9DFB 60 RTS ;return Z=1 iff field overflows
.QDFC ;Invert OSGBPB length field
9DFC A2 03 LDX #&03
.QDFE
9DFE A9 FF LDA #&FF
9E00 5D 65 10 EOR &1065,X
9E03 9D 65 10 STA &1065,X
9E06 CA DEX
9E07 10 F5 BPL QDFE
9E09 60 RTS
.QE0A ;Set up pointer to user's OSGBPB block
9E0A AD 7F 10 LDA &107F
9E0D 85 B4 STA &B4
9E0F AD 80 10 LDA &1080
9E12 85 B5 STA &B5
.QE14
9E14 60 RTS
.QE15 ;Get data byte from user memory
9E15 2C D5 10 BIT &10D5
9E18 30 03 BMI QE1D
9E1A B1 A6 LDA (&A6),Y
9E1C 60 RTS
.QE1D
9E1D AD E5 FE LDA &FEE5
9E20 60 RTS
.QE21 ;Put data byte in user memory
9E21 2C D5 10 BIT &10D5
9E24 30 03 BMI QE29
9E26 91 A6 STA (&A6),Y
9E28 60 RTS
.QE29
9E29 8D E5 FE STA &FEE5
9E2C 60 RTS
;*MCOPY and *COMPACT are the only two commands that copy files preserving
;their order, as EDOS's commands do. They are also the only two commands
;that use location &CC as a catalogue pointer... just like EDOS.
;*MCOPY
9E2D 20 3A A2 JSR R23A ;ensure *ENABLE active
9E30 20 DF A4 JSR R4DF ;call GSINIT and parse mandatory vol spec
9E33 8D D3 10 STA &10D3 ;set as source volume
9E36 20 DF A4 JSR R4DF ;call GSINIT and parse mandatory vol spec
9E39 8D D4 10 STA &10D4 ;set as destination volume
9E3C 20 27 A2 JSR R227 ;set swapping and current disc flags
9E3F 20 AC 9F JSR QFAC ;get start and size of user memory
9E42 20 32 86 JSR P632 ;load destination volume catalogue
9E45 20 15 85 JSR P515 ;save parameters of destination drive
9E48 AD 06 0F LDA &0F06 ;save destination volume size on stack
9E4B 48 PHA
9E4C AD 07 0F LDA &0F07
9E4F 48 PHA
9E50 20 84 9F JSR QF84 ;initialise LBA to start of data area
9E53 20 38 86 JSR P638 ;load source volume catalogue
9E56 20 0E 85 JSR P50E ;save parameters of source drive
9E59 AD 05 0F LDA &0F05 ;get number of files in catalogue * 8
9E5C 85 CC STA &CC ;store in catalogue pointer
9E5E F0 4F BEQ QEAF ;if no files then raise "File not found"
9E60 20 6D 9F JSR QF6D
9E63 68 PLA
9E64 85 C6 STA &C6
9E66 68 PLA
9E67 85 C7 STA &C7
9E69 29 0F AND #&0F
9E6B C5 CB CMP &CB
9E6D 90 08 BCC QE77
9E6F D0 09 BNE QE7A
9E71 A5 C6 LDA &C6
9E73 C5 CA CMP &CA
9E75 B0 03 BCS QE7A
.QE77
9E77 4C C3 85 JMP P5C3
.QE7A
9E7A A5 C7 LDA &C7
9E7C 48 PHA
9E7D A5 C6 LDA &C6
9E7F 48 PHA
9E80 20 FA 84 JSR P4FA ;restore parameters of destination drive
9E83 20 84 9F JSR QF84 ;initialise LBA to start of data area
9E86 20 38 86 JSR P638 ;load source volume catalogue
9E89 20 B2 9E JSR QEB2
9E8C 20 FA 84 JSR P4FA ;restore parameters of destination drive
9E8F 20 84 9F JSR QF84 ;initialise LBA to start of data area
9E92 20 6D 9F JSR QF6D
9E95 68 PLA
9E96 8D 07 0F STA &0F07
9E99 68 PLA
9E9A 8D 06 0F STA &0F06
9E9D 20 FA 84 JSR P4FA ;restore parameters of destination drive
9EA0 20 79 84 JSR P479 ;select destination volume
9EA3 20 81 92 JSR Q281 ;write volume catalogue
9EA6 20 BA 86 JSR P6BA ;do a NEW for BASIC
9EA9 A9 FF LDA #&FF
9EAB 8D 84 10 STA &1084 ;forget catalogue in pages &0E..F
9EAE 60 RTS
.QEAF
9EAF 4C 43 89 JMP P943 ;raise "File not found" error
.QEB2
9EB2 20 28 92 JSR Q228 ;set high word of OSFILE load address = &FFFF
9EB5 A9 00 LDA #&00
9EB7 85 BE STA &BE
9EB9 85 C2 STA &C2
9EBB AD 89 10 LDA &1089
9EBE 85 BF STA &BF
.QEC0
9EC0 A4 CC LDY &CC
9EC2 20 7B A4 JSR R47B ;subtract 8 from Y
9EC5 84 CC STY &CC
9EC7 20 C0 89 JSR P9C0 ;print *INFO line
9ECA A4 CC LDY &CC
9ECC 20 C4 A1 JSR R1C4
9ECF F0 57 BEQ QF28
9ED1 B9 0F 0F LDA &0F0F,Y
9ED4 85 C8 STA &C8
9ED6 B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
9ED9 29 03 AND #&03
9EDB 85 C9 STA &C9
9EDD 20 D0 A1 JSR R1D0 ;calculate number of sectors used by file
.QEE0
9EE0 38 SEC
9EE1 AD 8A 10 LDA &108A
9EE4 E5 BF SBC &BF
9EE6 A8 TAY
9EE7 A5 C7 LDA &C7
9EE9 D0 06 BNE QEF1
9EEB C4 C6 CPY &C6
9EED 90 02 BCC QEF1
9EEF A4 C6 LDY &C6
.QEF1
9EF1 84 C3 STY &C3
9EF3 A5 C8 LDA &C8
9EF5 85 C5 STA &C5
9EF7 A5 C9 LDA &C9
9EF9 85 C4 STA &C4
9EFB 20 F6 84 JSR P4F6 ;restore parameters of source drive
9EFE 20 6F 84 JSR P46F ;select source volume
9F01 20 0F 90 JSR Q00F ;read ordinary file L5
9F04 18 CLC
9F05 A5 C8 LDA &C8
9F07 65 C3 ADC &C3
9F09 85 C8 STA &C8
9F0B 90 02 BCC QF0F
9F0D E6 C9 INC &C9
.QF0F
9F0F 38 SEC
9F10 A5 C6 LDA &C6
9F12 E5 C3 SBC &C3
9F14 85 C6 STA &C6
9F16 B0 02 BCS QF1A
9F18 C6 C7 DEC &C7
.QF1A
9F1A 18 CLC
9F1B A5 BF LDA &BF
9F1D 65 C3 ADC &C3
9F1F 85 BF STA &BF
9F21 A5 BF LDA &BF
9F23 CD 8A 10 CMP &108A
9F26 F0 04 BEQ QF2C
.QF28
9F28 A4 CC LDY &CC
9F2A D0 94 BNE QEC0
.QF2C
9F2C AD 89 10 LDA &1089
9F2F C5 BF CMP &BF
9F31 F0 32 BEQ QF65
9F33 A5 CA LDA &CA
9F35 85 C5 STA &C5
9F37 A5 CB LDA &CB
9F39 85 C4 STA &C4
9F3B 38 SEC
9F3C A5 BF LDA &BF
9F3E ED 89 10 SBC &1089
9F41 85 C3 STA &C3
9F43 AD 89 10 LDA &1089
9F46 85 BF STA &BF
9F48 20 FA 84 JSR P4FA ;restore parameters of destination drive
9F4B 20 79 84 JSR P479 ;select destination volume
9F4E 20 09 90 JSR Q009 ;write ordinary file L5
9F51 18 CLC
9F52 A5 CA LDA &CA
9F54 65 C3 ADC &C3
9F56 85 CA STA &CA
9F58 90 02 BCC QF5C
9F5A E6 CB INC &CB
.QF5C
9F5C A5 C6 LDA &C6
9F5E 05 C7 ORA &C7
9F60 F0 03 BEQ QF65
9F62 4C E0 9E JMP QEE0
.QF65
9F65 A5 CC LDA &CC
9F67 F0 03 BEQ QF6C
9F69 4C C0 9E JMP QEC0
.QF6C
9F6C 60 RTS
.QF6D
9F6D AC 05 0F LDY &0F05 ;get number of files in catalogue * 8
.QF70
9F70 20 7B A4 JSR R47B ;subtract 8 from Y
9F73 C0 F8 CPY #&F8 ;loop until entire catalogue done
9F75 D0 01 BNE QF78
9F77 60 RTS
.QF78
9F78 20 9C 9F JSR QF9C ;set LBA of catalogue entry
9F7B 20 D0 A1 JSR R1D0 ;calculate number of sectors used by file
9F7E 20 19 A2 JSR R219 ;add number of sectors to total
9F81 4C 70 9F JMP QF70
.QF84 ;Initialise LBA to start of data area
9F84 A9 00 LDA #&00
9F86 85 CB STA &CB ;set MSB volume-relative LBA = 0
9F88 20 8E 9F JSR QF8E ;return no. reserved sectors in data area
9F8B 85 CA STA &CA ;set as LSB volume-relative LBA
9F8D 60 RTS
.QF8E ;Return no. reserved sectors in data area
9F8E A5 CF LDA &CF ;get current volume
9F90 29 0C AND #&0C ;is the physical drive a RAM disc?
9F92 D0 05 BNE QF99 ;if so then return A=2
9F94 2C E3 10 BIT &10E3 ;else A=0; test density flag
9F97 70 02 BVS QF9B ;if single density
.QF99
9F99 A9 02 LDA #&02 ;then return A=2
.QF9B
9F9B 60 RTS ;else return A=0
.QF9C ;Set LBA of catalogue entry
9F9C A5 CA LDA &CA ;Replace start sector of catalogue entry
9F9E 99 0F 0F STA &0F0F,Y ;with value in &CA..B
9FA1 B9 0E 0F LDA &0F0E,Y
9FA4 29 FC AND #&FC
9FA6 05 CB ORA &CB
9FA8 99 0E 0F STA &0F0E,Y
9FAB 60 RTS
.QFAC ;Get start and size of user memory
9FAC A9 83 LDA #&83 ;call OSBYTE &83 = read OSHWM
9FAE 20 F4 FF JSR &FFF4
9FB1 8C 89 10 STY &1089 ;save MSB
9FB4 A9 84 LDA #&84 ;call OSBYTE &84 = read HIMEM
9FB6 20 F4 FF JSR &FFF4
9FB9 98 TYA
9FBA 8D 8A 10 STA &108A ;save MSB
9FBD 38 SEC
9FBE ED 89 10 SBC &1089 ;subtract MSB of OSHWM
9FC1 8D 8B 10 STA &108B ;save result = no. pages of user memory.
9FC4 60 RTS
.QFC5
9FC5 A2 0A LDX #&0A ;service call &0A = workspace claimed
9FC7 20 18 A8 JSR R818 ;call OSBYTE &8F = issue service call
9FCA 20 D4 9F JSR QFD4 ;set up pointer to private page
9FCD A0 C1 LDY #&C1 ;set b7 of offset &C1 in private page
9FCF A9 FF LDA #&FF ;b7=1 iff we own the shared workspace
9FD1 91 B0 STA (&B0),Y
9FD3 60 RTS
.QFD4
9FD4 A6 F4 LDX &F4 ;Set up pointer to private page
9FD6 A9 00 LDA #&00
9FD8 85 B0 STA &B0
9FDA BD F0 0D LDA &0DF0,X
9FDD 85 B1 STA &B1
9FDF 60 RTS
;*HELP UTILS
9FE0 A2 5F LDX #&5F ;Print utility command table at &8E5F
9FE2 A0 8E LDY #&8E
9FE4 A9 08 LDA #&08 ;8 entries to print (not *DISK)
9FE6 D0 0E BNE QFF6
;*HELP DDOS / *HELP DFS
9FE8 A2 8A LDX #&8A ;Print DFS command table at &8D8A
9FEA A0 8D LDY #&8D
9FEC A9 15 LDA #&15 ;21 entries to print
9FEE D0 06 BNE QFF6
;*HELP DDOSX
9FF0 A2 35 LDX #&35 ;Print DDOSX command table at &8E35
9FF2 A0 8E LDY #&8E
9FF4 A9 04 LDA #&04 ;4 entries to print
.QFF6
9FF6 20 28 8F JSR PF28 ;set up trampoline to read table at XY
9FF9 85 B8 STA &B8 ;store number of printable entries in counter
9FFB 20 84 A8 JSR R884 ;print DDOS banner
9FFE A2 00 LDX #&00
.R000
A000 20 C9 A2 JSR R2C9 ;print two spaces
A003 20 27 A0 JSR R027
A006 20 67 84 JSR P467 ;print newline
A009 C6 B8 DEC &B8 ;decrement count of entries
A00B D0 F3 BNE R000 ;loop until none remain
A00D 60 RTS
.R00E
A00E 20 BB A4 JSR R4BB ;call GSINIT with C=0
A011 F0 01 BEQ R014 ;if string empty (and unquoted), syntax error
A013 60 RTS
.R014
A014 20 62 A3 JSR R362
A017 EQUB &DC
A018 EQUS "Syntax: "
A020 EQUB &EA
A021 20 27 A0 JSR R027
A024 4C B9 A3 JMP R3B9 ;terminate error message, raise error
.R027
A027 20 00 A3 JSR R300 ;save AXY
A02A A2 00 LDX #&00
A02C A0 09 LDY #&09
.R02E
A02E 20 AA 00 JSR &00AA
A031 30 08 BMI R03B
A033 20 03 A4 JSR R403 ;print character in A (OSASCI)
A036 E8 INX
A037 88 DEY
A038 4C 2E A0 JMP R02E
.R03B
A03B 88 DEY
A03C 30 04 BMI R042
A03E C8 INY
A03F 20 DA 88 JSR P8DA ;print number of spaces in Y
.R042
A042 E8 INX
A043 E8 INX
A044 20 AA 00 JSR &00AA
A047 48 PHA
A048 E8 INX
A049 20 37 8F JSR PF37 ;add X to trampoline address
A04C 68 PLA
A04D 20 55 A0 JSR R055
A050 20 67 A4 JSR R467 ;shift A right 4 places
A053 29 07 AND #&07
.R055
A055 20 00 A3 JSR R300 ;save AXY
A058 29 0F AND #&0F
A05A F0 1D BEQ R079
A05C A8 TAY
A05D A9 20 LDA #&20
A05F 20 03 A4 JSR R403 ;print character in A (OSASCI)
A062 A2 FF LDX #&FF
.R064
A064 E8 INX
A065 BD 7A A0 LDA &A07A,X
A068 D0 FA BNE R064
A06A 88 DEY
A06B D0 F7 BNE R064
.R06D
A06D E8 INX
A06E BD 7A A0 LDA &A07A,X
A071 F0 06 BEQ R079
A073 20 03 A4 JSR R403 ;print character in A (OSASCI)
A076 4C 6D A0 JMP R06D
.R079
A079 60 RTS
;Table of syntax elements
A07A EQUB &00 ;element &0, ""
A07B EQUS "" ;element &1,
A080 EQUB &00
A081 EQUS "" ;element &2,
A087 EQUB &00
A088 EQUS "(L)" ;element &3, (L)
A08B EQUB &00
A08C EQUS "" ;element &4,
A095 EQUB &00
A096 EQUS "" ;element &5,
A0A0 EQUB &00
A0A1 EQUS " " ;element &6,
A0B2 EQUB &00
A0B3 EQUS "" ;element &7,
A0BC EQUB &00
A0BD EQUS "" ;element &8,
A0C6 EQUB &00
A0C7 EQUS "()" ;element &9, ()
A0CE EQUB &00
A0CF EQUS "()" ;element &A, ()
A0D6 EQUB &00
A0D7 EQUS "" ;element &B,
A0DE EQUB &00
A0DF EQUS "" ;element &C,
A0E8 EQUB &00
A0E9 EQUS "" ;element &D,
A0F3 EQUB &00 ;terminator byte
;*COMPACT
A0F4 20 E5 A4 JSR R4E5 ;select specified or default volume
A0F7 8D D3 10 STA &10D3 ;set as source drive
A0FA 8D D4 10 STA &10D4 ;set as destination drive
A0FD 20 94 A3 JSR R394
A100 EQUS "Compacting"
A10A EA NOP
A10B 20 08 8D JSR PD08 ;print " Drive " plus volume spec in A
A10E 20 67 84 JSR P467 ;print newline
A111 A0 00 LDY #&00 ;point Y to workspace of invalid channel &10
A113 20 E2 95 JSR Q5E2 ;close file (does only ?&10C5 = 0: ?&10C9 = X)
A116 20 AC 9F JSR QFAC ;get start and size of user memory
A119 20 9E 92 JSR Q29E ;load volume catalogue L4
A11C 20 0E 85 JSR P50E ;save parameters of source drive
A11F 20 15 85 JSR P515 ;save parameters of destination drive
A122 AC 05 0F LDY &0F05 ;get number of files in catalogue
A125 84 CC STY &CC ;set as catalogue pointer
A127 20 84 9F JSR QF84 ;initialise LBA to start of data area
.R12A
A12A A4 CC LDY &CC ;set Y to catalogue pointer
A12C 20 7B A4 JSR R47B ;subtract 8 from Y
A12F C0 F8 CPY #&F8
A131 F0 54 BEQ R187
A133 84 CC STY &CC
A135 20 BB 89 JSR P9BB ;print *INFO line if verbose
A138 A4 CC LDY &CC
A13A 20 C4 A1 JSR R1C4
A13D F0 40 BEQ R17F
A13F A9 00 LDA #&00
A141 85 BE STA &BE
A143 85 C2 STA &C2
A145 20 D0 A1 JSR R1D0 ;calculate number of sectors used by file
A148 B9 0F 0F LDA &0F0F,Y
A14B 85 C8 STA &C8
A14D B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
A150 29 03 AND #&03
A152 85 C9 STA &C9
A154 C5 CB CMP &CB
A156 D0 0C BNE R164
A158 A5 C8 LDA &C8
A15A C5 CA CMP &CA
A15C D0 06 BNE R164
A15E 20 19 A2 JSR R219 ;add number of sectors to total
A161 4C 7F A1 JMP R17F
.R164
A164 A5 CA LDA &CA
A166 99 0F 0F STA &0F0F,Y
A169 B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
A16C 29 FC AND #&FC
A16E 05 CB ORA &CB
A170 99 0E 0F STA &0F0E,Y
A173 A9 00 LDA #&00
A175 85 A8 STA &A8
A177 85 A9 STA &A9
A179 20 51 87 JSR P751 ;copy source drive/file to destination
A17C 20 81 92 JSR Q281 ;write volume catalogue
.R17F
A17F A4 CC LDY &CC
A181 20 C0 89 JSR P9C0 ;print *INFO line
A184 4C 2A A1 JMP R12A
.R187
A187 20 94 A3 JSR R394
A18A EQUS "Disk compacted "
A199 EA NOP
A19A 38 SEC
A19B AD 07 0F LDA &0F07
A19E E5 CA SBC &CA
A1A0 48 PHA
A1A1 AD 06 0F LDA &0F06
A1A4 29 03 AND #&03
A1A6 E5 CB SBC &CB
A1A8 20 31 A4 JSR R431
A1AB 68 PLA
A1AC 20 29 A4 JSR R429 ;print hex byte
A1AF 20 94 A3 JSR R394
A1B2 EQUS " free sectors"
A1BF EQUB &0D
A1C0 EA NOP
A1C1 4C BA 86 JMP P6BA ;store empty BASIC program at OSHWM (NEW)
.R1C4
A1C4 B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
A1C7 29 30 AND #&30
A1C9 19 0D 0F ORA &0F0D,Y
A1CC 19 0C 0F ORA &0F0C,Y
A1CF 60 RTS
.R1D0 ;Calculate number of sectors used by file
A1D0 18 CLC
A1D1 B9 0C 0F LDA &0F0C,Y ;get LSB length
A1D4 69 FF ADC #&FF ;c=1 iff LSB >0
A1D6 B9 0D 0F LDA &0F0D,Y ;add C to 2MSB length, rounding up
A1D9 69 00 ADC #&00 ;(Y points to 8 bytes before file entry)
A1DB 85 C6 STA &C6
A1DD B9 0E 0F LDA &0F0E,Y ;get top bits exec/length/load/start sector
A1E0 08 PHP ;save carry flag from addition
A1E1 20 5F A4 JSR R45F ;extract length from b5,4 to b1,0
A1E4 28 PLP ;restore carry flag
A1E5 69 00 ADC #&00 ;add C to MSB length, rounding up
A1E7 85 C7 STA &C7 ;store length in sectors in zero page
A1E9 60 RTS
.R1EA ;Calculate free space on volume
A1EA 20 FF A1 JSR R1FF ;start with used space on volume
A1ED 38 SEC
A1EE AD 07 0F LDA &0F07 ;get LSB volume size from catalogue
A1F1 E5 CA SBC &CA ;subtract LSB used space
A1F3 85 C0 STA &C0 ;store LSB result in zero page
A1F5 AD 06 0F LDA &0F06 ;get boot option/top bits volume size
A1F8 29 03 AND #&03 ;extract MSB volume size
A1FA E5 CB SBC &CB ;subtract MSB used space, store in zp
A1FC 85 C1 STA &C1 ;(beware - can underflow due to overlaps)
A1FE 60 RTS
.R1FF ;Calculate used space on volume
A1FF AC 05 0F LDY &0F05 ;get number of files in catalogue * 8
A202 A9 00 LDA #&00 ;clear total number of used sectors on vol
A204 85 CA STA &CA
A206 85 CB STA &CB
.R208
A208 20 7B A4 JSR R47B ;subtract 8 from Y
A20B C0 F8 CPY #&F8 ;loop until entire catalogue done
A20D D0 01 BNE R210 ;(can exceed volume size due to overlaps)
A20F 60 RTS
.R210
A210 20 D0 A1 JSR R1D0 ;calculate number of sectors used by file
A213 20 19 A2 JSR R219 ;add number of sectors to total
A216 4C 08 A2 JMP R208 ;loop for next file
.R219 ;Add number of sectors to total
A219 18 CLC
A21A A5 CA LDA &CA
A21C 65 C6 ADC &C6
A21E 85 CA STA &CA
A220 A5 CB LDA &CB
A222 65 C7 ADC &C7
A224 85 CB STA &CB
A226 60 RTS
;Note: DDOS does not give the option to copy between opposite sides of
;different discs with one drive. *BACKUP 0 2 for instance copies one side
;of the disc to the other, without the chance to swap discs.
.R227 ;Set swapping and current disc flags
A227 A9 00 LDA #&00
A229 85 A9 STA &A9 ;&00 = source and dest. are different drives
A22B AD D4 10 LDA &10D4 ;get source drive
A22E CD D3 10 CMP &10D3 ;compare with destination drive
A231 D0 06 BNE R239 ;if equal
A233 A9 FF LDA #&FF ;then A=&FF
A235 85 A9 STA &A9 ;b7=1 source & dest. share drive (swapping)
A237 85 AA STA &AA ;b7=1 dest. disc in drive (ask for source)
.R239
A239 60 RTS
.R23A ;Ensure *ENABLE active
A23A 2C D2 10 BIT &10D2 ;test *ENABLE flag
A23D 10 5F BPL R29E ;if b7=0 then current command is enabled
A23F 20 62 A3 JSR R362 ;else raise "Not enabled" error.
A242 EQUB &BD
A243 EQUS "Not enabled"
A24E EQUB &00
.R24F ;Parse and print source and dest. volumes
A24F 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
A252 20 4F A5 JSR R54F ;parse volume spec
A255 8D D3 10 STA &10D3 ;store source volume
A258 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
A25B 20 4F A5 JSR R54F ;parse volume spec
A25E 8D D4 10 STA &10D4 ;store destination volume
A261 98 TYA ;save GSINIT offset in Y
A262 48 PHA
A263 20 27 A2 JSR R227 ;set swapping and current disc flags
A266 20 AC 9F JSR QFAC ;get start and size of user memory
A269 20 94 A3 JSR R394 ;print "Copying from drive "
A26C EQUS "Copying from drive "
A27F AD D3 10 LDA &10D3 ;get source volume
A282 20 BA 8B JSR PBBA ;print volume spec in A
A285 20 94 A3 JSR R394 ;print " to drive "
A288 EQUS " to drive "
A292 AD D4 10 LDA &10D4 ;get destination volume
A295 20 BA 8B JSR PBBA ;print volume spec in A
A298 20 67 84 JSR P467 ;print newline
A29B 68 PLA ;restore GSINIT offset to Y
A29C A8 TAY
A29D 18 CLC
.R29E
A29E 60 RTS
.R29F ;Increment and print BCD word
A29F F8 SED
A2A0 18 CLC
A2A1 A5 A8 LDA &A8
A2A3 69 01 ADC #&01
A2A5 85 A8 STA &A8
A2A7 A5 A9 LDA &A9
A2A9 69 00 ADC #&00
A2AB 85 A9 STA &A9
A2AD D8 CLD
A2AE 18 CLC
A2AF 20 B4 A2 JSR R2B4 ;print hex byte, C=0 if space-padded
A2B2 A5 A8 LDA &A8
.R2B4 ;Print hex byte, C=0 if space-padded
A2B4 48 PHA
A2B5 08 PHP
A2B6 20 67 A4 JSR R467 ;shift A right 4 places
A2B9 28 PLP
A2BA 20 BE A2 JSR R2BE ;print top nibble of byte
A2BD 68 PLA ;restore bottom nibble:
.R2BE ;Print space-padded hex nibble
A2BE 48 PHA
A2BF 68 PLA
A2C0 B0 02 BCS R2C4 ;if digit has been printed print another
A2C2 F0 08 BEQ R2CC ;else if nibble is zero print a space
.R2C4
A2C4 20 31 A4 JSR R431 ;else print hex nibble
A2C7 38 SEC ;set C=1 to suppress space padding
A2C8 60 RTS ;and exit
.R2C9 ;Print two spaces
A2C9 20 CC A2 JSR R2CC
.R2CC ;Print a space
A2CC 48 PHA
A2CD A9 20 LDA #&20
A2CF 20 03 A4 JSR R403 ;print character in A (OSASCI)
A2D2 68 PLA
A2D3 18 CLC
A2D4 60 RTS
.R2D5 ;Claim service call and set up argument ptr
A2D5 BA TSX
A2D6 A9 00 LDA #&00 ;have A=0 returned on exit
A2D8 9D 07 01 STA &0107,X
A2DB 98 TYA
A2DC 48 PHA
A2DD 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
A2E0 68 PLA
A2E1 A8 TAY
.R2E2
A2E2 98 TYA
A2E3 18 CLC
A2E4 65 F2 ADC &F2
A2E6 AA TAX
A2E7 A5 F3 LDA &F3
A2E9 69 00 ADC #&00
A2EB A8 TAY
A2EC A9 00 LDA #&00
A2EE 85 A8 STA &A8
A2F0 85 A9 STA &A9
A2F2 60 RTS
.R2F3 ;Have A=0 returned on exit
A2F3 48 PHA
A2F4 8A TXA
A2F5 48 PHA
A2F6 BA TSX
A2F7 A9 00 LDA #&00
A2F9 9D 09 01 STA &0109,X
A2FC 68 PLA
A2FD AA TAX
A2FE 68 PLA
A2FF 60 RTS
.R300 ;Save AXY
A300 48 PHA ;stack = &22,&A3,y,x,a,cl,ch,sl,sh
A301 8A TXA ;cl,ch=caller return address
A302 48 PHA ;sl,sh=superroutine return address
A303 98 TYA
A304 48 PHA
A305 A9 A3 LDA #&A3
A307 48 PHA
A308 A9 22 LDA #&22
A30A 48 PHA
.R30B
A30B A0 05 LDY #&05 ;duplicate y,x,a,cl,ch
.R30D
A30D BA TSX
A30E BD 07 01 LDA &0107,X
A311 48 PHA
A312 88 DEY
A313 D0 F8 BNE R30D
A315 A0 0A LDY #&0A ;copy top 10 bytes down 2 places:
.R317
A317 BD 09 01 LDA &0109,X ;overwrite bottom copy of cl,ch
A31A 9D 0B 01 STA &010B,X
A31D CA DEX
A31E 88 DEY ;stack now contains:
A31F D0 F6 BNE R317 ;y,x,y,x,a,cl,ch,&22,&A3,y,x,a,sl,sh
A321 68 PLA ;discard y,x:
A322 68 PLA
.R323
A323 68 PLA ;Restore AXY and return
A324 A8 TAY
A325 68 PLA
A326 AA TAX
A327 68 PLA
A328 60 RTS
.R329 ;Save XY
A329 48 PHA ;push y,x,a
A32A 8A TXA
A32B 48 PHA
A32C 98 TYA
A32D 48 PHA
A32E 20 0B A3 JSR R30B ;restack then "call" rest of caller's routine!
A331 BA TSX ;get stack pointer
A332 9D 03 01 STA &0103,X ;store A on exit from caller in stack:
A335 4C 23 A3 JMP R323 ;restore y,x on entry, a on exit.
.R338 ;Raise "Disk read only" error
A338 20 47 A3 JSR R347
A33B EQUB &C9
A33C EQUS " read only"
A346 EQUB &00
.R347
A347 20 8A A3 JSR R38A ;Raise "Disk " error
A34A EQUS "Disk "
A34F 90 11 BCC R362
.R351
A351 20 8A A3 JSR R38A ;Raise "Bad " error
A354 EQUS "Bad "
A358 90 08 BCC R362
.R35A
A35A 20 8A A3 JSR R38A ;Raise "File " error
A35D EQUS "File "
.R362
A362 85 B3 STA &B3
A364 68 PLA ;pop caller's address into pointer
A365 85 AE STA &AE
A367 68 PLA
A368 85 AF STA &AF
A36A A5 B3 LDA &B3
A36C 48 PHA
A36D 98 TYA
A36E 48 PHA
A36F A0 00 LDY #&00
A371 20 B4 A4 JSR R4B4 ;increment &AE,F
A374 B1 AE LDA (&AE),Y ;get error number from byte after JSR
A376 8D 01 01 STA &0101 ;store at bottom of stack
A379 2C DD 10 BIT &10DD ;if error message already being built
A37C 10 25 BPL R3A3 ;then complete it
A37E A9 02 LDA #&02 ;else A = &02
A380 8D DD 10 STA &10DD ;error message being built from offset 2
A383 A9 00 LDA #&00 ;instruction at &0100 = BRK
A385 8D 00 01 STA &0100
A388 F0 19 BEQ R3A3 ;build error message (always)
.R38A
A38A A9 02 LDA #&02 ;Add caller's prefix to super's error
A38C 8D DD 10 STA &10DD ;error message being built from offset 2
A38F A9 00 LDA #&00
A391 8D 00 01 STA &0100
.R394
A394 85 B3 STA &B3 ;Print string immediate
A396 68 PLA
A397 85 AE STA &AE
A399 68 PLA
A39A 85 AF STA &AF
A39C A5 B3 LDA &B3
A39E 48 PHA
A39F 98 TYA
A3A0 48 PHA
A3A1 A0 00 LDY #&00
.R3A3
A3A3 20 B4 A4 JSR R4B4 ;increment &AE,F
A3A6 B1 AE LDA (&AE),Y ;get character from after JSR
A3A8 30 08 BMI R3B2 ;if b7=1 then opcode terminator, execute it
A3AA F0 0D BEQ R3B9 ;else if NUL then raise error
A3AC 20 03 A4 JSR R403 ;else print the character
A3AF 4C A3 A3 JMP R3A3 ;and loop
.R3B2
A3B2 68 PLA ;restore AY
A3B3 A8 TAY
A3B4 68 PLA
A3B5 18 CLC
A3B6 6C AE 00 JMP (&00AE) ;jump to address of end of string
.R3B9 ;Terminate error message, raise error
A3B9 A9 00 LDA #&00
A3BB AE DD 10 LDX &10DD ;terminate error message with NUL
A3BE 9D 00 01 STA &0100,X
A3C1 A9 FF LDA #&FF ;no error message being built print to screen
A3C3 8D DD 10 STA &10DD
A3C6 8D 84 10 STA &1084 ;no catalogue in pages &0E..F
#if defined _DDOS316
A3C9 20 4B B7 JSR S74B ;no-op
#elif defined _DDOS336
A3C9 20 4B B7 JSR S74B ;no-op
#else
A3C9 20 49 B7 JSR S749 ;no-op
#endif
A3CC 20 45 93 JSR Q345 ;ensure Tube is released
A3CF 4C 00 01 JMP &0100 ;jump to BRK to raise error
.R3D2
A3D2 68 PLA ;Print VDU sequence immediate
A3D3 85 AE STA &AE ;pop caller's address into pointer
A3D5 68 PLA
A3D6 85 AF STA &AF
A3D8 A0 00 LDY #&00 ;offset = 0 for indirect indexed load
.R3DA
A3DA 20 B4 A4 JSR R4B4 ;increment &AE,F
A3DD B1 AE LDA (&AE),Y ;get character from after JSR
A3DF C9 FF CMP #&FF ;if &FF terminator byte
A3E1 F0 06 BEQ R3E9 ;then skip it and return to code after it
A3E3 20 EE FF JSR &FFEE ;else call OSWRCH
A3E6 4C DA A3 JMP R3DA ;and loop
.R3E9
A3E9 20 B4 A4 JSR R4B4 ;increment &AE,F
A3EC 6C AE 00 JMP (&00AE) ;jump to address at end of string
.R3EF ;Begin error message, number in A
A3EF 8D 01 01 STA &0101
A3F2 A9 00 LDA #&00
A3F4 8D 00 01 STA &0100
A3F7 A9 02 LDA #&02
A3F9 8D DD 10 STA &10DD
A3FC 60 RTS
.R3FD ;Print letter N
A3FD A9 4E LDA #&4E
A3FF D0 02 BNE R403 ;branch (always)
.R401 ;Print a dot
A401 A9 2E LDA #&2E
.R403 ;Print character in A (OSASCI)
A403 20 00 A3 JSR R300 ;save AXY
A406 2C DD 10 BIT &10DD
A409 10 14 BPL R41F
A40B 48 PHA
A40C 20 08 A8 JSR R808
A40F 8A TXA
A410 48 PHA
A411 09 10 ORA #&10
A413 20 03 A8 JSR R803
A416 68 PLA
A417 AA TAX
A418 68 PLA
A419 20 E3 FF JSR &FFE3
A41C 4C 04 A8 JMP R804
.R41F
A41F AE DD 10 LDX &10DD
A422 9D 00 01 STA &0100,X
A425 EE DD 10 INC &10DD
A428 60 RTS
.R429
A429 48 PHA ;Print hex byte
A42A 20 67 A4 JSR R467 ;shift A right 4 places
A42D 20 31 A4 JSR R431 ;print top nibble of byte
A430 68 PLA ;restore bottom nibble:
.R431
A431 48 PHA ;Print hex nibble
A432 29 0F AND #&0F
A434 F8 SED
A435 18 CLC
A436 69 90 ADC #&90
A438 69 40 ADC #&40
A43A D8 CLD
A43B 20 03 A4 JSR R403 ;print character in A (OSASCI)
A43E 68 PLA
A43F 60 RTS
.R440
A440 20 29 A3 JSR R329 ;save XY
A443 20 F7 A7 JSR R7F7
A446 C0 1B CPY #&1B
A448 D0 0D BNE R457
A44A 20 58 A4 JSR R458 ;acknowledge ESCAPE condition
A44D 20 A7 A7 JSR R7A7
A450 AE 10 10 LDX &1010
A453 9A TXS
A454 6C 11 10 JMP (&1011)
.R457
A457 60 RTS
.R458
A458 A9 7E LDA #&7E ;OSBYTE &7E = acknowledge ESCAPE condition
A45A 4C F4 FF JMP &FFF4 ;call OSBYTE and exit
.R45D ;Extract b7,b6 of A
A45D 4A LSR A
A45E 4A LSR A
.R45F ;Extract b5,b4 of A
A45F 4A LSR A
A460 4A LSR A
.R461 ;Extract b3,b2 of A
A461 4A LSR A
A462 4A LSR A
A463 29 03 AND #&03
A465 60 RTS
.R466 ;Shift A right 5 places
A466 4A LSR A
.R467 ;Shift A right 4 places
A467 4A LSR A
A468 4A LSR A
A469 4A LSR A
A46A 4A LSR A
A46B 60 RTS
;unreachable code
A46C 0A ASL A
.R46D ;Shift A left 4 places
A46D 0A ASL A
A46E 0A ASL A
A46F 0A ASL A
A470 0A ASL A
A471 60 RTS
.R472 ;Add 8 to Y
A472 C8 INY
.R473 ;Add 7 to Y
A473 C8 INY
A474 C8 INY
A475 C8 INY
#if defined _DFSFIX
.R476 ;Add 4 to Y
#endif
A476 C8 INY
A477 C8 INY
A478 C8 INY
A479 C8 INY
A47A 60 RTS
.R47B ;Subtract 8 from Y
A47B 88 DEY
A47C 88 DEY
A47D 88 DEY
A47E 88 DEY
A47F 88 DEY
A480 88 DEY
A481 88 DEY
A482 88 DEY
A483 60 RTS
.R484 ;Uppercase and validate letter in A
A484 C9 41 CMP #&41 ;is character less than capital A?
A486 90 0C BCC R494 ;if so then return C=1
A488 C9 5B CMP #&5B ;else is it more than capital Z?
A48A 90 0A BCC R496 ;if not then uppercase and return C=0
A48C C9 61 CMP #&61 ;else is it less than lowercase a?
A48E 90 04 BCC R494 ;if so then return C=1
A490 C9 7B CMP #&7B ;else is it more than lowercase z?
A492 90 02 BCC R496 ;if not then uppercase and return C=0
.R494
A494 38 SEC ;else return C=1
A495 60 RTS
.R496
A496 29 DF AND #&DF ;mask bit 5, convert letter to uppercase
A498 18 CLC
A499 60 RTS
.R49A ;Set C=0 iff character in A is a letter
A49A 48 PHA
A49B 20 84 A4 JSR R484 ;uppercase and validate letter in A
A49E 68 PLA
A49F 60 RTS
.R4A0
A4A0 20 AA A4 JSR R4AA ;Convert ASCII hex digit to binary
A4A3 90 03 BCC R4A8 ;C=0 iff digit valid
A4A5 C9 10 CMP #&10
A4A7 60 RTS
.R4A8
A4A8 38 SEC
A4A9 60 RTS
.R4AA
A4AA C9 41 CMP #&41 ;if digit is less than A
A4AC 90 02 BCC R4B0 ;then convert 0..9 to binary
A4AE E9 07 SBC #&07 ;else convert A..F to binary
.R4B0
A4B0 38 SEC
A4B1 E9 30 SBC #&30
A4B3 60 RTS
.R4B4
A4B4 E6 AE INC &AE ;Increment &AE,F
A4B6 D0 02 BNE R4BA
A4B8 E6 AF INC &AF
.R4BA
A4BA 60 RTS
.R4BB ;Call GSINIT with C=0
A4BB 18 CLC ;c=0 space or CR terminates unquoted strings
A4BC 4C C2 FF JMP &FFC2 ;jump to GSINIT
.R4BF ;Set current drive from ASCII digit
A4BF 38 SEC
A4C0 E9 30 SBC #&30 ;convert ASCII digit to binary
A4C2 90 4D BCC R511 ;if invalid raise "Bad drive" error
A4C4 85 CF STA &CF ;else set current drive=digit, volume=A
#if defined _RAMBUGFIX
A4C6 C9 22 CMP #&22 ;was drive number capital R?
A4C8 4C 09 A5 JMP R509 ;if so replace with 4 else accept digits 0..7.
#else
A4C6 A5 CF LDA &CF ;get current volume
A4C8 4C 8F A5 JMP R58F ;ensure drive number in range 0..3.
#endif
.R4CB ;Set volume from ASCII letter
A4CB 20 84 A4 JSR R484 ;uppercase and validate letter in A
A4CE 38 SEC ;subtract ASCII value of A
A4CF E9 41 SBC #&41 ;obtain ordinal 0..25
A4D1 90 3E BCC R511 ;if ordinal negative then "Bad drive"
A4D3 C9 08 CMP #&08 ;else is ordinal 8 or more?
A4D5 B0 3A BCS R511 ;if so then raise "Bad drive" error
A4D7 20 6D A4 JSR R46D ;else shift A left 4 places
A4DA 05 CF ORA &CF ;combine volume letter with current drive
A4DC 85 CF STA &CF ;set as current volume, return C=0
A4DE 60 RTS
.R4DF ;Call GSINIT and parse mandatory vol spec
A4DF 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
A4E2 4C 4F A5 JMP R54F ;parse volume spec
.R4E5 ;Select specified or default volume
A4E5 20 BB A4 JSR R4BB ;call GSINIT with C=0
A4E8 F0 16 BEQ R500 ;if argument empty select default volume
A4EA 20 4F A5 JSR R54F ;else parse volume spec
A4ED 4C D6 A7 JMP R7D6 ;set up for current drive and exit
.R4F0
A4F0 AD CA 10 LDA &10CA ;get default directory
A4F3 85 CE STA &CE ;set as current directory
A4F5 AD CB 10 LDA &10CB ;get default volume
#if defined _RAMBUGFIX
.R4F8
#endif
A4F8 85 CF STA &CF ;set as current volume
A4FA 60 RTS
.R4FB
A4FB AD CA 10 LDA &10CA ;get default directory
A4FE 85 CE STA &CE ;set as current directory
.R500
A500 AD CB 10 LDA &10CB ;get default volume:
.R503 ;Select volume in A
A503 85 CF STA &CF ;save as current volume
A505 20 D6 A7 JSR R7D6 ;set up for drive
#if defined _RAMBUGFIX
A508 60 RTS
.R509
A509 D0 02 BNE R50D ;if drive number equals R
A50B A9 04 LDA #&04 ;then substitute drive 4
.R50D
A50D C9 08 CMP #&08 ;if drive number in range 0..7
A50F 90 E7 BCC R4F8 ;then save it as current drive
#else
.R508
A508 60 RTS
;unreachable code
A509 20 E5 A4 JSR R4E5 ;select specified or default volume
A50C 20 BB A4 JSR R4BB ;call GSINIT with C=0
A50F F0 F7 BEQ R508 ;if no more arguments then return
#endif
.R511 ;else raise "Bad drive" error.
A511 20 51 A3 JSR R351
A514 EQUB &CD
A515 EQUS "drive"
A51A EQUB &00
.R51B ;Parse directory spec
A51B 20 C5 FF JSR &FFC5 ;call GSREAD
A51E B0 2E BCS R54E ;if end of argument then exit C=1
A520 C9 3A CMP #&3A ;else is character a colon?
A522 D0 22 BNE R546 ;if not then accept directory character
A524 20 C5 FF JSR &FFC5 ;else call GSREAD
A527 B0 E8 BCS R511 ;if ":" by itself then "Bad drive" error
A529 20 BF A4 JSR R4BF ;else set current drive from ASCII digit
A52C 20 C5 FF JSR &FFC5 ;call GSREAD
A52F B0 1D BCS R54E ;if ":" keep current volume and dir
A531 C9 2E CMP #&2E ;else is character a full stop?
A533 F0 0C BEQ R541 ;if so then expect a directory character
A535 20 CB A4 JSR R4CB ;else set volume from ASCII letter
A538 20 C5 FF JSR &FFC5 ;call GSREAD
A53B B0 11 BCS R54E ;if ":" keep current directory
A53D C9 2E CMP #&2E ;else "." must follow
A53F D0 D0 BNE R511 ;if next char not full stop "Bad drive"
.R541
A541 20 C5 FF JSR &FFC5 ;else call GSREAD
A544 B0 CB BCS R511 ;directory char expected else "Bad drive"
.R546
A546 20 80 A5 JSR R580 ;set directory from ASCII character
A549 20 C5 FF JSR &FFC5 ;if not at end of argument
A54C 90 C3 BCC R511 ;then raise "Bad drive" error.
.R54E
A54E 60 RTS
.R54F ;Parse volume spec
A54F A2 00 LDX #&00 ;x=0, nothing specified
A551 20 C5 FF JSR &FFC5 ;call GSREAD
A554 B0 F8 BCS R54E ;if end of argument then exit C=1
A556 08 PHP ;else save status, C=0
A557 C9 3A CMP #&3A ;is character a colon?
A559 D0 05 BNE R560 ;if not then set drive from digit
A55B 20 C5 FF JSR &FFC5 ;else call GSREAD
A55E B0 B1 BCS R511 ;if ":" by itself then "Bad drive" error
.R560
A560 20 BF A4 JSR R4BF ;set current drive from ASCII digit
A563 A2 02 LDX #&02 ;x=2, only drive specified
A565 20 C5 FF JSR &FFC5 ;call GSREAD
A568 B0 0F BCS R579 ;if no more chars return drive, volume=A
A56A 28 PLP ;else restore status, C=0
A56B 90 07 BCC R574 ;set volume and return current volume
#if defined _BEEBEM
;Shoddy trick to get BeebEm to write the last byte of a track. DO NOT USE
;Trampoline called from &0D1B (&BA3F)
A56D 8D 00 0D STA &0D00 ;store 0D00=RTI ignore further NMIs
A570 A9 CE LDA #&CE ;set A=&CE counter for 123 us delay
A572 08 PHP ;save status; RTI unfreezes BeebEm's WD 1770
A573 40 RTI ;return to &0D1D and execute opcode &0D
#else
;unreachable code
A56D C9 2A CMP #&2A
A56F D0 03 BNE R574
A571 A2 83 LDX #&83
A573 60 RTS
#endif
.R574
A574 20 CB A4 JSR R4CB ;set volume letter from ASCII letter
A577 E8 INX ;x=1, drive and volume specified
A578 08 PHP ;save status, C=0
.R579
A579 28 PLP ;restore status, C=0
A57A A5 CF LDA &CF ;get current volume and exit
A57C 60 RTS
;unreachable code
A57D 20 C5 FF JSR &FFC5
.R580 ;Set directory from ASCII character
A580 C9 2A CMP #&2A ;make * an alias of #
A582 D0 02 BNE R586
A584 A9 23 LDA #&23
.R586
A586 85 CE STA &CE ;set as current directory
A588 18 CLC
A589 60 RTS
#if defined _DDOS357
A58B EQUB &25,&26,&35,&36
#else
;unreachable code
;Convert ASCII drive number to binary
A58A 38 SEC
A58B E9 30 SBC #&30
A58D 90 05 BCC R594 ;if invalid then raise "Bad drive" error
#endif
#if defined _RAMBUGFIX
;unreachable code
#else
.R58F ;Ensure drive number in range
#endif
A58F C9 04 CMP #&04 ;0..3
A591 B0 01 BCS R594 ;if invalid then raise "Bad drive" error
A593 60 RTS ;else exit
.R594
A594 4C 11 A5 JMP R511 ;raise "Bad drive" error
.R597 ;Set current vol/dir from open filename
A597 B9 0E 11 LDA &110E,Y ;get directory character of open file
A59A 29 7F AND #&7F ;mask off b7 =channel file locked bit
A59C 85 CE STA &CE ;set as current directory
A59E B9 1F 11 LDA &111F,Y ;get volume containing open file
A5A1 4C 03 A5 JMP R503 ;select volume in A and exit
.R5A4 ;Detect disc format/set sector address
A5A4 A9 00 LDA #&00 ;set track number = 0
A5A6 85 BA STA &BA
A5A8 A5 CF LDA &CF ;get current volume
A5AA 29 0C AND #&0C ;if b3 or b2 are set
A5AC D0 57 BNE R605 ;then a RAM drive so set up for RAM disc
#if defined _DDOS316
A5AE 20 7E B6 JSR S67E ;else recalibrate drive (seek track 0)
#elif defined _DDOS336
A5AE 20 7E B6 JSR S67E ;else recalibrate drive (seek track 0)
#else
A5AE 20 7C B6 JSR S67C ;else recalibrate drive (seek track 0)
#endif
A5B1 AD 00 10 LDA &1000 ;if data transfer call is not 0 = read data
A5B4 D0 5A BNE R610 ;then set sector number = 2 * volume letter
A5B6 A9 00 LDA #&00 ;else data area starts on track 0
A5B8 8D E2 10 STA &10E2
A5BB 20 1F A6 JSR R61F ;set number of sectors per track
A5BE 2C E3 10 BIT &10E3 ;if disc is double density
A5C1 70 09 BVS R5CC ;then accept any volume letter
A5C3 A5 CF LDA &CF ;else get current volume
A5C5 29 F0 AND #&F0 ;extract volume letter
A5C7 F0 03 BEQ R5CC ;if volume letter is not A
A5C9 4C 11 A5 JMP R511 ;then raise "Bad drive" error
.R5CC
A5CC 2C E0 10 BIT &10E0 ;if double-stepping is automatic
A5CF 10 03 BPL R5D4
A5D1 20 31 A6 JSR R631 ;then detect track stepping
.R5D4
A5D4 2C E3 10 BIT &10E3 ;if disc is single density
A5D7 50 37 BVC R610 ;then set sector number = 0
A5D9 20 F5 AF JSR RFF5 ;else copy volume allocations to wksp
A5DC AD 00 0E LDA &0E00 ;test configuration/version number
A5DF C9 E5 CMP #&E5 ;of disc catalogue
A5E1 D0 03 BNE R5E6 ;if byte is &E5 formatting fill byte
A5E3 4C 7E A6 JMP R67E ;then "Disk not configured by VOLGEN"
.R5E6
A5E6 AD 01 0E LDA &0E01 ;get number of sectors on surface
A5E9 8D 0E 10 STA &100E ;save in workspace
A5EC AD 02 0E LDA &0E02
A5EF 8D 0F 10 STA &100F
A5F2 AD 03 0E LDA &0E03 ;get number of sectors per track
A5F5 8D E1 10 STA &10E1 ;save in workspace
A5F8 20 15 A6 JSR R615 ;set sector number = 2 * volume letter
A5FB A8 TAY ;= offset into the track allocation table
A5FC B9 08 0E LDA &0E08,Y ;get first track of volume from disc cat.
A5FF 8D E2 10 STA &10E2 ;set as first track of current volume
A602 F0 54 BEQ R658 ;if =0 raise "Volume . not allocated" error
A604 60 RTS
.R605 ;Set up for RAM disc
A605 A9 00 LDA #&00
A607 8D E1 10 STA &10E1 ;number of sectors per track is undefined
A60A 8D E2 10 STA &10E2 ;data area starts on track 0
A60D 85 BB STA &BB ;sector number = 0
A60F 60 RTS
.R610 ;Set sector number = 2 * volume letter
A610 AD E3 10 LDA &10E3 ;test density flag
A613 F0 07 BEQ R61C ;if single (and manual!) then start sector =0
.R615
A615 A5 CF LDA &CF ;else get current volume
A617 29 F0 AND #&F0 ;extract volume letter
A619 4A LSR A ;shift right three places
A61A 4A LSR A ;to get sector offset of volume catalogue
A61B 4A LSR A
.R61C
A61C 85 BB STA &BB ;set as sector number
A61E 60 RTS
.R61F ;Set number of sectors per track
A61F 2C E3 10 BIT &10E3 ;if density setting is automatic
A622 10 03 BPL R627
#if defined _DDOS316
A624 4C C4 B6 JMP S6C4 ;then ensure disc is formatted
#elif defined _DDOS336
A624 4C C4 B6 JMP S6C4 ;then ensure disc is formatted
#else
A624 4C C2 B6 JMP S6C2 ;then ensure disc is formatted
#endif
.R627
A627 A9 0A LDA #&0A ;else set 10 sectors per track
A629 50 02 BVC R62D ;unless disc is double density
A62B A9 12 LDA #&12 ;in which case set 18 sectors per track
.R62D
A62D 8D E1 10 STA &10E1
A630 60 RTS
.R631 ;Detect track stepping
A631 A9 80 LDA #&80 ;b7=1 automatic, b6=0 1:1 stepping
A633 8D E0 10 STA &10E0 ;set stepping flag
A636 A9 02 LDA #&02 ;track number = 2
#if defined _DDOS316
A638 20 99 B6 JSR S699 ;seek physical track
A63B 20 14 B7 JSR S714
#elif defined _DDOS336
A638 20 99 B6 JSR S699 ;seek physical track
A63B 20 14 B7 JSR S714
#else
A638 20 97 B6 JSR S697 ;seek physical track
A63B 20 12 B7 JSR S712 ;execute Read Address command
#endif
A63E AE 02 10 LDX &1002 ;get C cylinder number
A641 CA DEX ;is it 1?
A642 F0 0A BEQ R64E ;then disc is 40 track, set double stepping
A644 CA DEX ;else is it 2?
A645 F0 0C BEQ R653 ;then 1:1 stepping is correct, recalibrate
A647 CA DEX ;else the format is wrong, raise an error
A648 CA DEX ;is the head over logical track 4?
A649 D0 55 BNE R6A0 ;if not then raise "Bad track format" error
A64B 4C B5 A6 JMP R6B5 ;else "80 track disk in 40 track drive".
.R64E
A64E A9 C0 LDA #&C0 ;b7=1 automatic, b6=1 2:1 stepping
A650 8D E0 10 STA &10E0 ;set stepping flag
.R653
A653 A9 00 LDA #&00 ;track number = 0
#if defined _DDOS316
A655 4C 99 B6 JMP S699 ;seek physical track
#elif defined _DDOS336
A655 4C 99 B6 JMP S699 ;seek physical track
#else
A655 4C 97 B6 JMP S697 ;seek physical track
#endif
.R658 ;Raise "Volume . not allocated" error
A658 20 62 A3 JSR R362 ;begin error message "Volume "
A65B EQUB &CD
A65C EQUS "Volume "
A663 EA NOP
A664 18 CLC
A665 98 TYA ;transfer sector offset to A
A666 4A LSR A ;divide by 2; A=0..7, C=0
A667 69 41 ADC #&41 ;convert to ASCII character "A".."H"
A669 20 03 A4 JSR R403 ;print character in A (to error message)
A66C 20 94 A3 JSR R394 ;print " not allocated" and raise error
A66F EQUS " not allocated"
A67D EQUB &00
.R67E
A67E 20 62 A3 JSR R362
A681 EQUB &CD
A682 EQUS "Disk not configured by VOLGEN"
A69F EQUB &00
.R6A0
A6A0 20 62 A3 JSR R362
A6A3 EQUB &CD
A6A4 EQUS "Bad track format"
A6B4 EQUB &00
.R6B5
A6B5 20 62 A3 JSR R362
A6B8 EQUB &CD
A6B9 EQUS "80 track disk in 40 track drive"
A6D8 EQUB &00
.R6D9 ;Load disc catalogue L3
A6D9 A9 00 LDA #&00 ;data transfer call &00 = read data
A6DB F0 02 BEQ R6DF ;branch (always)
.R6DD ;Write disc catalogue L3
A6DD A9 01 LDA #&01 ;data transfer call &01 = write data
.R6DF
A6DF 8D 00 10 STA &1000 ;set data transfer call number
A6E2 A2 03 LDX #&03 ;x = 3 number of attempts allowed:
.R6E4
A6E4 20 ED 92 JSR Q2ED ;set data pointer to &0E00
A6E7 A9 10 LDA #&10 ;set sector number = 16
A6E9 85 BB STA &BB
A6EB A9 00 LDA #&00 ;set track number = 0
A6ED 85 BA STA &BA
A6EF 85 A0 STA &A0 ;&0100 = 256 bytes to transfer
A6F1 A9 01 LDA #&01
A6F3 85 A1 STA &A1
#if defined _DDOS316
A6F5 20 5F B7 JSR S75F ;transfer data to disc L2
#elif defined _DDOS336
A6F5 20 5F B7 JSR S75F ;transfer data to disc L2
#else
A6F5 20 5D B7 JSR S75D ;transfer data to disc L2
#endif
A6F8 D0 01 BNE R6FB ;if command failed try again
A6FA 60 RTS ;else exit
.R6FB
A6FB CA DEX ;decrement attempts remaining
A6FC D0 E6 BNE R6E4 ;if not run out then try again
#if defined _DDOS316
A6FE 4C 95 B9 JMP S995 ;else raise "Disk fault" error
#elif defined _DDOS336
A6FE 4C 93 B9 JMP S993 ;else raise "Disk fault" error
#else
A6FE 4C B6 B9 JMP S9B6 ;else raise "Disk fault" error
#endif
;unreachable code
A701 60 RTS
.R702 ;Transfer data and report errors L4
A702 20 00 A3 JSR R300 ;save AXY
A705 20 15 A7 JSR R715 ;transfer data L3
A708 D0 01 BNE R70B ;if non-zero status report error
A70A 60 RTS ;else return
.R70B
A70B 29 40 AND #&40
A70D D0 03 BNE R712 ;if b6=0 WD1770 S6 = write protect
#if defined _DDOS316
A70F 4C 95 B9 JMP S995 ;then raise "Disk fault" error
#elif defined _DDOS336
A70F 4C 93 B9 JMP S993 ;then raise "Disk fault" error
#else
A70F 4C B6 B9 JMP S9B6 ;then raise "Disk fault" error
#endif
.R712
A712 4C 38 A3 JMP R338 ;else raise "Disk read only" error
;[BUG] OSFILE does not load or save files 64 KiB or larger to the RAM
;disc correctly. Only the requested length of data modulo 64 KiB
;(&10000 bytes) is transferred. The rest of the file is unread or
;undefined. Such calls are only relevant to large coprocessors.
;The RAM disc code transfers up to 64 KiB at a time between the RAM disc
;and user memory. Files on the RAM disc are treated specially here and
;moved in a single operation. They can't be split into 'tracks' to
;work around the limit because the RAM code has different variables at
;locations &A0..7 which the floppy-oriented track advance code would
;clobber. This only matters when saving and loading files to a large
;coprocessor (using OSFILE). Just use OSFIND and OSGBPB instead.
.R715 ;Transfer data L3
A715 20 29 A3 JSR R329 ;save XY
A718 A9 05 LDA #&05 ;set attempt counter to 5
A71A 8D 2A 10 STA &102A
.R71D
A71D AD E1 10 LDA &10E1 ;get number of sectors per track
A720 08 PHP ;save Z flag
A721 A6 A3 LDX &A3 ;set X=LSB byte count
A723 A5 A4 LDA &A4 ;set A=2MSB byte count
A725 28 PLP ;restore Z flag
A726 F0 18 BEQ R740 ;if 0 sectors per track then RAM disc, branch
A728 38 SEC ;else subtract
A729 AD E1 10 LDA &10E1 ;number of sectors per track
A72C E5 BB SBC &BB ;- starting sector
A72E 85 A0 STA &A0 ;= sectors until end, store temp
A730 A5 A5 LDA &A5 ;test MSB byte count
A732 D0 08 BNE R73C ;if >=64 KiB then transfer rest of track
A734 A6 A3 LDX &A3 ;else X=LSB byte count (redundant to &A721)
A736 A5 A4 LDA &A4 ;set Y=2MSB byte count
A738 C5 A0 CMP &A0 ;if transfer ends before end of track
A73A 90 04 BCC R740 ;then only transfer byte count, else:
.R73C ;transfer rest of track
A73C A2 00 LDX #&00 ;X=0 byte count is a multiple of 256
A73E A5 A0 LDA &A0 ;A=number of sectors (not bytes) to transfer:
.R740
A740 8E 85 10 STX &1085 ;store LSB byte count
A743 8D 86 10 STA &1086 ;store MSB byte count
A746 86 A0 STX &A0 ;store LSB byte count
A748 85 A1 STA &A1 ;store MSB byte count
A74A 05 A0 ORA &A0 ;test if byte count > 0
A74C F0 53 BEQ R7A1 ;if no data to transfer then finish
A74E 20 67 B4 JSR S467 ;else transfer data L2
A751 F0 0C BEQ R75F ;if zero status then continue
A753 29 40 AND #&40 ;else if b6=1 WD1770 S6 = write protect
A755 D0 07 BNE R75E ;then return
A757 CE 2A 10 DEC &102A ;decrement attempt counter
A75A D0 C1 BNE R71D ;if not tried 5 times then try again
A75C A9 01 LDA #&01 ;else return A=1, Z=0
.R75E
A75E 60 RTS
.R75F
A75F E6 BA INC &BA ;increment track
A761 A9 00 LDA #&00
A763 85 BB STA &BB ;next transfer starts at sector 0
A765 18 CLC
A766 AD 86 10 LDA &1086 ;add MSB of expected transfer size
A769 6D 6E 10 ADC &106E ;to 3MSB Tube transfer address? (and discard!)
;[BUG] ?&106E is constant, high word either
;never changes or increments every track
A76C 90 08 BCC R776 ;carry out to high word of Tube transfer addr
A76E EE 6F 10 INC &106F ;= high word of OSFILE load address
A771 D0 03 BNE R776
A773 EE 70 10 INC &1070
.R776
A776 18 CLC ;add expected transfer size to xfer. address
A777 A5 A6 LDA &A6
A779 6D 85 10 ADC &1085
A77C 85 A6 STA &A6
A77E A5 A7 LDA &A7
A780 6D 86 10 ADC &1086
A783 85 A7 STA &A7
A785 38 SEC ;subtract expected transfer size
A786 A5 A3 LDA &A3 ;from 24-bit byte count
A788 ED 85 10 SBC &1085
A78B 85 A3 STA &A3
A78D A5 A4 LDA &A4
A78F ED 86 10 SBC &1086
A792 85 A4 STA &A4
A794 B0 02 BCS R798
A796 C6 A5 DEC &A5
.R798
A798 05 A3 ORA &A3 ;test remaining no. bytes to transfer
A79A 05 A5 ORA &A5
A79C F0 03 BEQ R7A1 ;if no more data to transfer then finish
A79E 4C 1D A7 JMP R71D ;else loop to transfer rest of file.
.R7A1
A7A1 20 A7 A7 JSR R7A7 ;release NMI
A7A4 A9 00 LDA #&00 ;fake WD1770 status = 0, succeeded.
A7A6 60 RTS
.R7A7
A7A7 2C 87 10 BIT &1087 ;Release NMI
A7AA 10 0C BPL R7B8 ;if NMI is not already ours then exit
A7AC AC 88 10 LDY &1088 ;else Y = ID of previous NMI owner
A7AF C0 FF CPY #&FF ;if Y=&FF no previous owner
A7B1 F0 05 BEQ R7B8 ;then skip release call
A7B3 A2 0B LDX #&0B ;else service call &0B = NMI release
A7B5 20 18 A8 JSR R818 ;call OSBYTE &8F = issue service call
.R7B8
A7B8 A9 00 LDA #&00
A7BA 8D 87 10 STA &1087
#if defined _DDOS316
A7BD 20 4B B7 JSR S74B ;no-op
#elif defined _DDOS336
A7BD 20 4B B7 JSR S74B ;no-op
#else
A7BD 20 49 B7 JSR S749 ;no-op
#endif
A7C0 60 RTS
.R7C1
A7C1 2C 87 10 BIT &1087 ;Claim NMI
A7C4 30 0F BMI R7D5 ;if NMI is already ours then exit
A7C6 A9 8F LDA #&8F ;else OSBYTE &8F = issue service call
A7C8 A2 0C LDX #&0C ;service call &0C = claim NMI
A7CA 20 20 A8 JSR R820 ;call OSBYTE with Y=&FF
A7CD 8C 88 10 STY &1088 ;save ID of previous NMI owner
A7D0 A9 FF LDA #&FF ;set NMI ownership flag
A7D2 8D 87 10 STA &1087 ;b7=1 iff we own the NMI
.R7D5
A7D5 60 RTS
.R7D6
A7D6 A5 CF LDA &CF ;Set up for current drive
A7D8 29 0C AND #&0C
A7DA D0 03 BNE R7DF ;if (drive number mod 16) = 0..3
A7DC 20 58 B6 JSR S658 ;then set control latch for drive
.R7DF
A7DF A5 CF LDA &CF ;restore drive number to A
A7E1 60 RTS
.R7E2 ;Test write protect state of current drive
A7E2 A5 CF LDA &CF ;get current volume
A7E4 29 0C AND #&0C ;is the physical drive a RAM disc?
A7E6 D0 03 BNE R7EB ;if so return Z=1, write enabled
#if defined _DDOS316
A7E8 4C 75 B6 JMP S675 ;else test write protect state
#elif defined _DDOS336
A7E8 4C 75 B6 JMP S675 ;else test write protect state
#else
A7E8 4C 73 B6 JMP S673 ;else test write protect state
#endif
.R7EB
A7EB A9 00 LDA #&00
A7ED 60 RTS
.R7EE ;Call *FX 15,1 = clear input buffer
A7EE 20 00 A3 JSR R300 ;save AXY
A7F1 A9 0F LDA #&0F
A7F3 A2 01 LDX #&01
A7F5 D0 08 BNE R7FF
.R7F7
A7F7 A9 81 LDA #&81
A7F9 D0 02 BNE R7FD
.R7FB ;Disable *SPOOL output
A7FB A9 C7 LDA #&C7 ;OSBYTE &C7 = read/write *SPOOL file handle
.R7FD ;Call OSBYTE with X=0, Y=0
A7FD A2 00 LDX #&00
.R7FF ;Call OSBYTE with Y=0
A7FF A0 00 LDY #&00
A801 F0 1F BEQ R822 ;call OSBYTE
.R803
A803 AA TAX
.R804
A804 A9 03 LDA #&03
A806 D0 1A BNE R822
.R808
A808 A9 EC LDA #&EC
A80A D0 12 BNE R81E
.R80C ;Call OSBYTE &C7 = read/write *SPOOL handle
A80C A9 C7 LDA #&C7
A80E D0 0E BNE R81E
.R810 ;Call OSBYTE &EA = read Tube presence flag
A810 A9 EA LDA #&EA
A812 D0 0A BNE R81E
.R814 ;Call OSBYTE &A8 = get ext. vector table addr
A814 A9 A8 LDA #&A8
A816 D0 06 BNE R81E
.R818 ;Call OSBYTE &8F = issue service call
A818 A9 8F LDA #&8F
A81A D0 06 BNE R822
.R81C ;Call OSBYTE &FF = read/write startup options
A81C A9 FF LDA #&FF
.R81E
A81E A2 00 LDX #&00
.R820
A820 A0 FF LDY #&FF
.R822
A822 4C F4 FF JMP &FFF4
;Table of addresses of extended vector handlers
A825 EQUW &1B,&FF ;FILEV, &0212 = &FF1B
A827 EQUW &1E,&FF ;ARGSV, &0214 = &FF1E
A829 EQUW &21,&FF ;BGETV, &0216 = &FF21
A82B EQUW &24,&FF ;BPUTV, &0218 = &FF24
A82D EQUW &27,&FF ;GBPBV, &021A = &FF27
A82F EQUW &2A,&FF ;FINDV, &021C = &FF2A
A831 EQUW &2D,&FF ;FSCV, &021E = &FF2D
;Table of action addresses for extended vector table
A833 EQUW &DC,&9A ;E FILEV, evt + &1B = &9ADC
A835 EQUW &94,&97 ;E ARGSV, evt + &1E = &9794
A837 EQUW &DA,&98 ;E BGETV, evt + &21 = &98DA
A839 EQUW &B6,&99 ;E BPUTV, evt + &24 = &99B6
A83B EQUW &2D,&9C ;E GBPBV, evt + &27 = &9C2D
#if defined _DFSFIX
A83D EQUW &D2,&BF ;E FINDV, evt + &2A = &BFD2
#else
A83D EQUW &C1,&95 ;E FINDV, evt + &2A = &95C1
#endif
#if defined _DDOS357
A83F EQUW &E8,&BF ;E FSCV, evt + &2D = &BFE8
#else
A83F EQUW &68,&94 ;E FSCV, evt + &2D = &9468
#endif
;Table of action addresses for OSFSC calls 0..8, low bytes
A841 EQUB &7A ;OSFSC 0 = *OPT &947B
A842 EQUB &B5 ;OSFSC 1 = read EOF state &94B6
A843 EQUB &CD ;OSFSC 2 = */ &94CE
A844 EQUB &4A ;OSFSC 3 = unrecognised *cmd &954B
A845 EQUB &CD ;OSFSC 4 = *RUN &94CE
A846 EQUB &5C ;OSFSC 5 = *CAT &955D
A847 EQUB &74 ;OSFSC 6 = new FS starting up &9575
A848 EQUB &7C ;OSFSC 7 = valid file handles &957D
A849 EQUB &81 ;OSFSC 8 = *command entered &9582
;Table of action addresses for OSFSC calls 0..8, high bytes
A84A EQUB &94
A84B EQUB &94
A84C EQUB &94
A84D EQUB &95
A84E EQUB &94
A84F EQUB &95
A850 EQUB &95
A851 EQUB &95
A852 EQUB &95
;Table of action addresses for OSARGS calls A=&FF,0,1, Y=0, low bytes
A853 EQUB &D0 ;OSARGS &FF = ensure all files &97D1
A854 EQUB &BA ;OSARGS 0 = return FS number &97BB
A855 EQUB &BD ;OSARGS 1 = command line tail &97BE
;Table of action addresses for OSARGS calls A=&FF,0,1, Y=0, high bytes
A856 EQUB &97
A857 EQUB &97
A858 EQUB &97
;Table of action addresses for OSFILE calls &FF,0..6, low bytes
A859 EQUB &55 ;OSFILE &FF = load file &9B56
A85A EQUB &0A ;OSFILE 0 = save file &9B0B
A85B EQUB &16 ;OSFILE 1 = wr. catalog info &9B17
A85C EQUB &21 ;OSFILE 2 = wr. load address &9B22
A85D EQUB &29 ;OSFILE 3 = wr. exec address &9B2A
A85E EQUB &31 ;OSFILE 4 = wr. attributes &9B32
A85F EQUB &40 ;OSFILE 5 = read catalog info &9B41
A860 EQUB &49 ;OSFILE 6 = delete file &9B4A
;Table of action addresses for OSFILE calls &FF,0..6, low bytes
A861 EQUB &9B
A862 EQUB &9B
A863 EQUB &9B
A864 EQUB &9B
A865 EQUB &9B
A866 EQUB &9B
A867 EQUB &9B
A868 EQUB &9B
;Table of action addresses for OSGBPB calls 0..8, low bytes
A869 EQUB &E9 ;OSGBPB 0 = no operation &9CE9
A86A EQUB &EA ;OSGBPB 1 = set PTR and write &9CEA
A86B EQUB &EA ;OSGBPB 2 = write data &9CEA
A86C EQUB &F2 ;OSGBPB 3 = set PTR and read &9CF2
A86D EQUB &F2 ;OSGBPB 4 = read data &9CF2
A86E EQUB &FA ;OSGBPB 5 = read title/opt/drv &9CFA
A86F EQUB &2B ;OSGBPB 6 = read CSD drv/dir &9D2B
A870 EQUB &3A ;OSGBPB 7 = read lib'y drv/dir &9D3A
A871 EQUB &49 ;OSGBPB 8 = read CSD filenames &9D49
;Table of action addresses for OSGBPB calls 0..8, high bytes
A872 EQUB &9C
A873 EQUB &9C
A874 EQUB &9C
A875 EQUB &9C
A876 EQUB &9C
A877 EQUB &9C
A878 EQUB &9D
A879 EQUB &9D
A87A EQUB &9D
;Table of microcode bytes for OSGBPB calls 0..8
A87B EQUB &04 ;%000001 0 . to memory, special handler
A87C EQUB &02 ;%000000 1 0 from memory, xfer data, set PTR
A87D EQUB &03 ;%000000 1 1 from memory, xfer data, leave PTR
A87E EQUB &06 ;%000001 1 0 to memory, xfer data, set PTR
A87F EQUB &07 ;%000001 1 1 to memory, xfer data, leave PTR
A880 EQUB &04 ;%000001 0 . to memory, special handler
A881 EQUB &04 ;%000001 0 . to memory, special handler
A882 EQUB &04 ;%000001 0 . to memory, special handler
A883 EQUB &04 ;%000001 0 . to memory, special handler
.R884
A884 20 94 A3 JSR R394 ;Print DDOS banner
#if defined _DDOS316
A887 EQUS "OPUS DDOS 3.16"
#elif defined _DDOS336
A887 EQUS "OPUS DDOS 3.36"
#elif defined _DDOS356
A887 EQUS "FTC DDOS v3.56"
#elif defined _DDOS357
A887 EQUS "FTC DDOS v3.58"
#else
A887 EQUS "OPUS DDOS 3.46"
#endif
A895 EQUB &0D
A896 EQUB &0D
A897 EA NOP
A898 60 RTS
#if defined _DDOS316
A899 EQUB &03,&16 ;bcd version number = 3.16
#elif defined _DDOS336
A899 EQUB &03,&36 ;bcd version number = 3.36
#elif defined _DDOS346
A899 EQUB &03,&46 ;bcd version number = 3.46
#else
A899 EQUB &03,&45 ;bcd version number = 3.45
#endif
A89B EQUB &01,&03,&86 ;bcd date dd/mm/yy = 1 March 1986
A89E EQUB &00,&00,&00 ;bcd revision number = 0 (printed as spaces)
;*FORMAT
A8A1 A9 05 LDA #&05 ;set drive number = 5 (unused)
A8A3 85 BC STA &BC
A8A5 A9 00 LDA #&00
A8A7 85 BD STA &BD ;clear interleaved format flag
A8A9 20 BB A4 JSR R4BB ;call GSINIT with C=0
A8AC F0 13 BEQ R8C1 ;if argument empty then skip
A8AE 20 C5 FF JSR &FFC5 ;else call GSREAD
A8B1 C9 49 CMP #&49 ;does argument begin with capital I?
A8B3 D0 07 BNE R8BC ;if not then extract drive number
A8B5 C6 BD DEC &BD ;else set interleaved format flag (unused)
A8B7 20 C5 FF JSR &FFC5 ;call GSREAD, read next argument character
A8BA B0 05 BCS R8C1 ;if end of string then skip
.R8BC
A8BC 20 A0 A4 JSR R4A0 ;else convert ASCII hex digit to binary
A8BF 85 BC STA &BC ;save as drive number (unused)
.R8C1
A8C1 20 F3 A2 JSR R2F3 ;have A=0 returned on exit
A8C4 BA TSX
A8C5 8E 10 10 STX &1010
A8C8 8E 24 10 STX &1024 ;set stack pointer to restore on exit
A8CB 20 28 92 JSR Q228 ;set high word of buffer address = &FFFF
;command restart point set at &A93F
A8CE 20 39 AA JSR RA39 ;set command restart to exit command
A8D1 20 74 AD JSR RD74 ;set display MODE 7
A8D4 20 38 AD JSR RD38 ;print "DISK FORMATTER" heading
.R8D7
A8D7 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
A8DA EQUB &1F ;move cursor to (0,21)
A8DB EQUB &00
A8DC EQUB &15
A8DD EQUB &83 ;yellow alphanumerics
A8DE EQUS "Input no. of tracks (35/40/80) "
A905 EQUB &7F
A906 EQUB &7F
A907 EQUB &7F
A908 EQUB &7F
A909 EQUB &7F
A90A EQUB &7F
A90B EQUB &7F
A90C EQUB &7F
A90D EQUB &FF
A90E 20 F4 AD JSR RDF4 ;input number up to 5 digits
A911 98 TYA ;if user entered no digits
A912 F0 C3 BEQ R8D7 ;then repeat prompt and input
A914 20 09 B1 JSR S109 ;else convert ASCII numeric to unsigned word
A917 B0 20 BCS R939 ;if numeric invalid then display error
A919 A2 50 LDX #&50 ;else 80 tracks maximum can be formatted
A91B AD E0 10 LDA &10E0 ;test double-stepping flag
A91E 10 05 BPL R925 ;if double-stepping is automatic
A920 29 80 AND #&80 ;then discard last detected setting
A922 8D E0 10 STA &10E0 ;and force 1:1 stepping
.R925
A925 2C E0 10 BIT &10E0 ;(else) test double-stepping flag
A928 50 02 BVC R92C ;if *4080 ON, forced double-stepping
A92A A2 28 LDX #&28 ;then maximum format is 40 tracks.
.R92C
A92C E4 B0 CPX &B0 ;compare max - LSB of number entered
A92E 90 09 BCC R939 ;if max < LSB then display error
A930 A5 B0 LDA &B0 ;else set A = LSB number of tracks requested
A932 F0 05 BEQ R939 ;0 track format is not sensible, display error
A934 85 C0 STA &C0 ;else set number of tracks to format
A936 4C 3F A9 JMP R93F ;(can be any number up to maximum)
.R939
A939 20 C2 B0 JSR S0C2 ;briefly display error indication
A93C 4C D7 A8 JMP R8D7 ;and re-prompt and input number of tracks
.R93F
A93F A2 CE LDX #&CE ;point XY at *FORMAT entry point, &A8CE
A941 A0 A8 LDY #&A8
A943 20 3D AA JSR RA3D ;set command restart action address
A946 20 D7 AD JSR RDD7 ;clear row 23
.R949
A949 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
A94C EQUB &1F ;move cursor to (0,22)
A94D EQUB &00
A94E EQUB &16
A94F EQUB &83 ;yellow alphanumerics
A950 EQUS "Drive number (0/1/2/3) "
A967 EQUB &FF
A968 20 87 B0 JSR S087 ;get printable input character
A96B C9 30 CMP #&30 ;is it less than ASCII "0"?
A96D 90 DA BCC R949 ;if so then input new drive number
A96F E9 30 SBC #&30 ;else convert to binary drive no. 0..3
A971 C9 04 CMP #&04 ;is drive number in range?
A973 90 06 BCC R97B ;if so then proceed
A975 20 C2 B0 JSR S0C2 ;else briefly display error indication
A978 4C 3F A9 JMP R93F ;and input new drive number
.R97B
A97B 85 CF STA &CF ;set as current volume
A97D 20 D7 AD JSR RDD7 ;clear row 23
.R980
A980 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
A983 EQUB &1F ;move cursor to (0,23)
A984 EQUB &00
A985 EQUB &17
A986 EQUB &83 ;yellow alphanumerics
A987 EQUS "Density (S/D) "
A995 EQUB &FF
A996 20 87 B0 JSR S087 ;get printable input character
A999 C9 53 CMP #&53 ;is it capital S?
A99B F0 0A BEQ R9A7 ;if so then format single density
A99D C9 44 CMP #&44 ;else is it capital D?
A99F F0 09 BEQ R9AA ;if so then format double density
A9A1 20 C2 B0 JSR S0C2 ;else briefly display error indication
A9A4 4C 80 A9 JMP R980 ;and re-input; [BUG] old density on screen!
.R9A7
A9A7 4C F5 A9 JMP R9F5 ;jump to format single density (was in range)
.R9AA
A9AA A2 CE LDX #&CE ;point XY at *FORMAT entry point, &A8CE
A9AC A0 A8 LDY #&A8
A9AE 20 3D AA JSR RA3D ;set command restart action address
A9B1 AD E3 10 LDA &10E3 ;set double density
A9B4 09 40 ORA #&40 ;preserve automatic setting bit 7
A9B6 8D E3 10 STA &10E3 ;set double density bit 6
A9B9 A9 12 LDA #&12 ;set 18 sectors per track
A9BB 8D E1 10 STA &10E1
A9BE 20 D6 A7 JSR R7D6 ;set up for current drive
A9C1 A9 00 LDA #&00
A9C3 8D 13 10 STA &1013 ;set return code = 0, no error
A9C6 20 97 B1 JSR S197 ;prompt user and start format
A9C9 AD 13 10 LDA &1013 ;test return code
A9CC F0 03 BEQ R9D1
A9CE 4C F2 A9 JMP R9F2 ;exit command
.R9D1
A9D1 20 B3 AE JSR REB3 ;clear pages &0E,&0F
A9D4 20 C0 AE JSR REC0
A9D7 A6 C0 LDX &C0
A9D9 CA DEX
A9DA 86 B0 STX &B0
A9DC 20 25 B0 JSR S025
A9DF 20 CB AE JSR RECB
A9E2 20 1D AF JSR RF1D ;write volume catalogues
A9E5 20 41 AF JSR RF41 ;generate disc catalogue
A9E8 20 DD A6 JSR R6DD ;write disc catalogue L3
A9EB A2 77 LDX #&77 ;point XY to "Please wait" at &BE77
A9ED A0 B3 LDY #&B3
A9EF 20 A4 AD JSR RDA4 ;erase VDU sequence at XY
.R9F2
A9F2 4C 44 AA JMP RA44 ;exit command
.R9F5
A9F5 A2 CE LDX #&CE ;point XY at *FORMAT entry point, &A8CE
A9F7 A0 A8 LDY #&A8
A9F9 20 3D AA JSR RA3D ;set command restart action address
A9FC AD E3 10 LDA &10E3 ;set single density
A9FF 29 80 AND #&80 ;preserve automatic setting bit 7
AA01 8D E3 10 STA &10E3 ;clear double density bit 6
AA04 A9 0A LDA #&0A ;set 10 sectors per track
AA06 8D E1 10 STA &10E1
AA09 20 D6 A7 JSR R7D6 ;set up for current drive
AA0C A9 00 LDA #&00
AA0E 8D 13 10 STA &1013 ;set return code = 0, no error
AA11 20 97 B1 JSR S197 ;prompt user and start format
AA14 AD 13 10 LDA &1013 ;test return code
AA17 D0 1D BNE RA36
AA19 A6 C0 LDX &C0
AA1B 86 B0 STX &B0
AA1D 20 25 B0 JSR S025
AA20 20 B3 AE JSR REB3 ;clear pages &0E,&0F
AA23 A5 C5 LDA &C5
AA25 8D 06 0F STA &0F06
AA28 A5 C4 LDA &C4
AA2A 8D 07 0F STA &0F07
AA2D A9 00 LDA #&00
AA2F 85 BA STA &BA
AA31 85 BB STA &BB
AA33 20 CE 92 JSR Q2CE ;write disc/volume catalogue L3
.RA36
AA36 4C 44 AA JMP RA44 ;exit command on restart
.RA39 ;Set command restart to exit command
AA39 A2 44 LDX #&44 ;point XY at command exit routine, &AA44
AA3B A0 AA LDY #&AA
.RA3D ;Set command restart action address
AA3D 8E 11 10 STX &1011
AA40 8C 12 10 STY &1012
AA43 60 RTS
.RA44 ;Exit command on restart
AA44 AE 24 10 LDX &1024 ;restore stack pointer from workspace
AA47 9A TXS
AA48 20 8B B1 JSR S18B ;clear rows 20..22
AA4B A2 00 LDX #&00 ;set XY to screen coordinates (0,24)
AA4D A0 18 LDY #&18
AA4F 20 80 AD JSR RD80 ;move cursor to (X,Y)
#if defined _DDOS316
AA52 4C 4B B7 JMP S74B ;exit (jump to RTS)
#elif defined _DDOS336
AA52 4C 4B B7 JMP S74B ;exit (jump to RTS)
#else
AA52 4C 49 B7 JMP S749 ;exit (jump to RTS)
#endif
;*VERIFY
AA55 20 E5 A4 JSR R4E5 ;select specified or default volume
AA58 BA TSX
AA59 8E 24 10 STX &1024
AA5C 8E 10 10 STX &1010
AA5F 20 F3 A2 JSR R2F3 ;have A=0 returned on exit
AA62 20 28 92 JSR Q228 ;set high word of OSFILE load address = &FFFF
;command restart point set at &AAAC
AA65 20 39 AA JSR RA39 ;set command restart to exit command
AA68 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
AA6B EQUB &16 ;set MODE 7
AA6C EQUB &07
AA6D EQUB &0A ;print two newlines
AA6E EQUB &0A
AA6F EQUB &FF
AA70 A2 02 LDX #&02 ;repeat next line twice:
.RA72
AA72 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
AA75 EQUB &83 ;yellow alphanumerics
AA76 EQUB &8D ;double height
AA77 EQUS " V E R I F Y D I S K"
AA91 EQUB &0D
AA92 EQUB &0A
AA93 EQUB &FF
AA94 CA DEX ;loop until line printed twice
AA95 D0 DB BNE RA72
AA97 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
AA9A EQUB &1F ;move cursor to (0,10)
AA9B EQUB &00
AA9C EQUB &0A
AA9D EQUS "Insert disk"
AAA8 EQUB &FF
AAA9 20 E4 B2 JSR S2E4 ;prompt for keypress
AAAC A2 65 LDX #&65 ;point XY at *VERIFY entry point, &AA65
AAAE A0 AA LDY #&AA
AAB0 20 3D AA JSR RA3D ;set command restart action address
AAB3 20 74 AD JSR RD74 ;set display MODE 7
AAB6 A9 00 LDA #&00
AAB8 8D 00 10 STA &1000
AABB 20 A4 A5 JSR R5A4 ;detect disc format/set sector address
AABE 2C E3 10 BIT &10E3 ;test density flag
AAC1 70 20 BVS RAE3 ;if double density then examine disc catalog
AAC3 20 A1 92 JSR Q2A1 ;else load volume catalogue
AAC6 AD 06 0F LDA &0F06 ;get boot option/top bits volume size
AAC9 29 03 AND #&03 ;extract top bits volume size
AACB 85 B1 STA &B1 ;store MSB of dividend
AACD AD 07 0F LDA &0F07 ;get LSB volume size
AAD0 85 B0 STA &B0 ;store LSB of dividend
AAD2 A9 00 LDA #&00
AAD4 85 B3 STA &B3 ;clear MSB of divisor
AAD6 AD E1 10 LDA &10E1 ;get number of sectors per track (= 10)
AAD9 85 B2 STA &B2 ;store LSB of divisor
AADB 20 3C AE JSR RE3C ;divide word by word
AADE 86 C0 STX &C0 ;store quotient as number of tracks
AAE0 4C EB AA JMP RAEB ;verify disc
.RAE3
AAE3 20 D9 A6 JSR R6D9 ;load disc catalogue L3
AAE6 AD 04 0E LDA &0E04 ;get number of tracks on disc
AAE9 85 C0 STA &C0 ;store number of tracks to verify
.RAEB ;Verify disc
AAEB A9 00 LDA #&00
AAED 85 BA STA &BA ;set starting sector = 0
AAEF 8D 13 10 STA &1013 ;set return code = 0, no error
.RAF2
AAF2 20 53 B2 JSR S253 ;print track number in table
AAF5 20 28 AB JSR RB28 ;verify track with display
AAF8 F0 03 BEQ RAFD ;if hard error occurred
AAFA EE 13 10 INC &1013 ;then set return code > 0, verify failed
.RAFD
AAFD E6 BA INC &BA ;increment track number
AAFF A5 BA LDA &BA ;compare track number - number of tracks
AB01 C5 C0 CMP &C0
AB03 90 ED BCC RAF2 ;if less then verify next track
AB05 AD 13 10 LDA &1013 ;else test return code
AB08 D0 37 BNE RB41 ;if error occurred print "VERIFY ERROR"
AB0A 20 D2 A3 JSR R3D2 ;else print VDU sequence immediate
AB0D EQUB &1F ;move cursor to (10,23)
AB0E EQUB &0A
AB0F EQUB &17
AB10 EQUB &83 ;yellow alphanumerics
AB11 EQUS "Verify complete"
AB20 EQUB &0D
AB21 EQUB &FF
#if defined _DDOS316
AB22 20 7E B6 JSR S67E ;recalibrate drive (seek track 0)
#elif defined _DDOS336
AB22 20 7E B6 JSR S67E ;recalibrate drive (seek track 0)
#else
AB22 20 7C B6 JSR S67C ;recalibrate drive (seek track 0)
#endif
AB25 4C 44 AA JMP RA44 ;exit command on restart
.RB28 ;Verify track with display
AB28 A2 06 LDX #&06 ;make 6 attempts
AB2A A0 06 LDY #&06 ;erase next 6 characters
AB2C 20 08 B3 JSR S308 ;erase Y characters ahead of cursor
.RB2F
AB2F 20 40 A4 JSR R440
#if defined _DDOS316
AB32 20 4C B7 JSR S74C ;verify track
#elif defined _DDOS336
AB32 20 4C B7 JSR S74C ;verify track
#else
AB32 20 4A B7 JSR S74A ;verify track
#endif
AB35 F0 09 BEQ RB40 ;if verify succeeded then exit
AB37 A9 2E LDA #&2E ;else print a dot
AB39 20 EE FF JSR &FFEE ;call OSWRCH
AB3C CA DEX ;decrement attempt counter
AB3D D0 F0 BNE RB2F ;if attempts remaining then try again
AB3F CA DEX ;else X=&FF, Z=0 to indicate failure
.RB40
AB40 60 RTS
.RB41
AB41 20 67 B1 JSR S167 ;print "VERIFY ERROR"
AB44 4C 44 AA JMP RA44 ;exit command on restart
;*VOLGEN
AB47 20 3A A2 JSR R23A ;ensure *ENABLE active
AB4A 20 E5 A4 JSR R4E5 ;select specified or default volume
AB4D BA TSX
AB4E 8E 24 10 STX &1024
AB51 20 F3 A2 JSR R2F3 ;have A=0 returned on exit
AB54 20 28 92 JSR Q228 ;set high word of OSFILE load address = &FFFF
AB57 20 39 AA JSR RA39 ;set command restart to exit command
#if defined _DDOS316
AB5A 20 7E B6 JSR S67E ;recalibrate drive (seek track 0)
#elif defined _DDOS336
AB5A 20 7E B6 JSR S67E ;recalibrate drive (seek track 0)
#else
AB5A 20 7C B6 JSR S67C ;recalibrate drive (seek track 0)
#endif
AB5D A9 00 LDA #&00
AB5F 8D E2 10 STA &10E2 ;data area starts on track 0
AB62 20 0F AD JSR RD0F ;ensure disc is double density
AB65 A5 CF LDA &CF ;get current volume
AB67 29 03 AND #&03 ;extract physical drive number, clear b7..2
AB69 85 CF STA &CF ;set current volume letter to A
AB6B 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
AB6E EQUB &16
AB6F EQUB &07
AB70 EQUB &0A
AB71 EQUB &0A
AB72 EQUB &FF
AB73 A2 02 LDX #&02
.RB75
AB75 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
AB78 EQUB &83 ;yellow alphanumerics
AB79 EQUB &8D ;double height
AB7A EQUS "V O L U M E G E N E R A T I O N"
AB9B EQUB &0D
AB9C EQUB &0A
AB9D EQUB &FF
AB9E CA DEX
AB9F D0 D4 BNE RB75
ABA1 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
ABA4 EQUB &1F ;move cursor to (0,7)
ABA5 EQUB &00
ABA6 EQUB &07
ABA7 EQUB &0D
ABA8 EQUB &83 ;yellow alphanumerics
ABA9 EQUS "Vol Size (K) "
ABB7 EQUB &FF
ABB8 A5 CF LDA &CF ;get current volume
ABBA 20 08 8D JSR PD08 ;print " Drive " plus volume spec in A
ABBD 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
ABC0 EQUB &0D ;carriage return
ABC1 EQUB &0A ;two line feeds
#if defined _BEEBEM
;Shoddy trick to get BeebEm to write the last byte of a track. DO NOT USE
ABC2 EQUB &FF
ABC3 A2 41 LDX #&41
.RBC5
ABC5 20 D2 A3 JSR R3D2
ABC8 EQUB &0D
ABC9 EQUB &0A
ABCA EQUB &83
ABCB EQUS " "
ABCC EQUB &FF
ABCD 8A TXA
ABCE 20 03 A4 JSR R403
ABD1 E8 INX
ABD2 E0 49 CPX #&49
ABD4 D0 EF BNE RBC5
ABD6 20 D2 A3 JSR R3D2
ABD9 EQUB &0D
ABDA EQUB &0A
ABDB EQUB &0A
ABDC EQUB &83 ;yellow alphanumerics
ABDD EQUS "No. of Kbytes remaining"
ABF4 EQUB &FF
ABF5 20 AB AF JSR RFAB
ABF8 A2 00 LDX #&00
ABFA F0 0E BEQ RC0A
.RBFC
ABFC A0 06 LDY #&06 ;7 bytes to copy:
.RBFE
ABFE B9 6D A5 LDA &A56D,Y ;get byte of trampoline code
AC01 99 3D 0D STA &0D3D,Y ;store in NMI area
AC04 88 DEY ;loop until 7 bytes copied
AC05 10 F7 BPL RBFE
AC07 4C 31 B8 JMP S831 ;copy NMI read from disc/polling loop and exit
#else /* _BEEBEM */
ABC2 EQUB &0A
ABC3 EQUB &83 ;yellow alphanumerics
ABC4 EQUS " A"
ABC6 EQUB &0D ;carriage return
ABC7 EQUB &0A ;line feed
ABC8 EQUB &83 ;yellow alphanumerics
ABC9 EQUS " B"
ABCB EQUB &0D
ABCC EQUB &0A
ABCD EQUB &83 ;yellow alphanumerics
ABCE EQUS " C"
ABD0 EQUB &0D
ABD1 EQUB &0A
ABD2 EQUB &83 ;yellow alphanumerics
ABD3 EQUS " D"
ABD5 EQUB &0D
ABD6 EQUB &0A
ABD7 EQUB &83 ;yellow alphanumerics
ABD8 EQUS " E"
ABDA EQUB &0D
ABDB EQUB &0A
ABDC EQUB &83 ;yellow alphanumerics
ABDD EQUS " F"
ABDF EQUB &0D
ABE0 EQUB &0A
ABE1 EQUB &83 ;yellow alphanumerics
ABE2 EQUS " G"
ABE4 EQUB &0D
ABE5 EQUB &0A
ABE6 EQUB &83 ;yellow alphanumerics
ABE7 EQUS " H"
ABE9 EQUB &0D
ABEA EQUB &0A
ABEB EQUB &0A
ABEC EQUB &83 ;yellow alphanumerics
ABED EQUS "No. of Kbytes remaining"
AC04 EQUB &FF
AC05 20 AB AF JSR RFAB
AC08 A2 00 LDX #&00
#endif /* _BEEBEM */
.RC0A
AC0A 86 C1 STX &C1
AC0C 8A TXA
AC0D 48 PHA
AC0E 20 8D AE JSR RE8D
AC11 68 PLA
AC12 AA TAX
AC13 E8 INX
AC14 E0 08 CPX #&08
AC16 D0 F2 BNE RC0A
.RC18
AC18 20 3D B0 JSR S03D
AC1B A5 C2 LDA &C2
AC1D 85 B0 STA &B0
AC1F A5 C3 LDA &C3
AC21 4A LSR A
AC22 66 B0 ROR &B0
AC24 4A LSR A
AC25 66 B0 ROR &B0
AC27 85 B1 STA &B1
AC29 20 5D AE JSR RE5D ;convert binary word to four decimal digits
AC2C A2 19 LDX #&19
AC2E A0 12 LDY #&12
AC30 20 80 AD JSR RD80 ;move cursor to (X,Y)
AC33 20 66 B0 JSR S066 ;print four decimal digits, space-padded
AC36 4C 3C AC JMP RC3C
.RC39
AC39 20 C2 B0 JSR S0C2 ;briefly display error indication
.RC3C
AC3C A2 18 LDX #&18
AC3E A0 B3 LDY #&B3
AC40 20 8D AD JSR RD8D ;print VDU sequence at XY
AC43 20 AA B0 JSR S0AA ;get input character and acknowledge ESCAPE
AC46 C9 0D CMP #&0D
AC48 D0 03 BNE RC4D
AC4A 4C F1 AC JMP RCF1
.RC4D
AC4D 38 SEC
AC4E E9 41 SBC #&41
AC50 90 E7 BCC RC39
AC52 C9 08 CMP #&08
AC54 B0 E3 BCS RC39
AC56 85 C1 STA &C1
AC58 69 41 ADC #&41
AC5A 20 EE FF JSR &FFEE
AC5D A9 20 LDA #&20
AC5F 20 EE FF JSR &FFEE
AC62 20 F4 AD JSR RDF4 ;input number up to 5 digits
AC65 B0 D5 BCS RC3C
AC67 98 TYA
AC68 D0 17 BNE RC81
AC6A A5 C1 LDA &C1
AC6C 0A ASL A
AC6D A8 TAY
AC6E A9 00 LDA #&00
AC70 99 14 10 STA &1014,Y
AC73 99 15 10 STA &1015,Y
AC76 20 E9 AD JSR RDE9
AC79 A2 04 LDX #&04
AC7B 20 E0 AD JSR RDE0 ;print X spaces
AC7E 4C 18 AC JMP RC18
.RC81
AC81 20 09 B1 JSR S109 ;convert ASCII numeric to unsigned word
AC84 B0 B3 BCS RC39
AC86 A5 B1 LDA &B1
AC88 F0 06 BEQ RC90
AC8A 20 C2 B0 JSR S0C2 ;briefly display error indication
AC8D 4C 3C AC JMP RC3C
.RC90
AC90 06 B0 ASL &B0
AC92 26 B1 ROL &B1
AC94 06 B0 ASL &B0
AC96 26 B1 ROL &B1
AC98 A9 00 LDA #&00
AC9A 85 B2 STA &B2
AC9C 85 B3 STA &B3
.RC9E
AC9E 38 SEC
AC9F A5 B0 LDA &B0
ACA1 E9 12 SBC #&12
ACA3 85 B0 STA &B0
ACA5 A5 B1 LDA &B1
ACA7 E9 00 SBC #&00
ACA9 85 B1 STA &B1
ACAB 90 0E BCC RCBB
ACAD 18 CLC
ACAE A9 12 LDA #&12
ACB0 65 B2 ADC &B2
ACB2 85 B2 STA &B2
ACB4 90 02 BCC RCB8
ACB6 E6 B3 INC &B3
.RCB8
ACB8 4C 9E AC JMP RC9E
.RCBB
ACBB A5 C1 LDA &C1
ACBD 0A ASL A
ACBE A8 TAY
ACBF A9 00 LDA #&00
ACC1 99 14 10 STA &1014,Y
ACC4 99 15 10 STA &1015,Y
ACC7 20 3D B0 JSR S03D
ACCA 38 SEC
ACCB A5 C2 LDA &C2
ACCD E5 B2 SBC &B2
ACCF A5 C3 LDA &C3
ACD1 E5 B3 SBC &B3
ACD3 B0 08 BCS RCDD
ACD5 A5 C2 LDA &C2
ACD7 85 B2 STA &B2
ACD9 A5 C3 LDA &C3
ACDB 85 B3 STA &B3
.RCDD
ACDD A5 C1 LDA &C1
ACDF 0A ASL A
ACE0 A8 TAY
ACE1 A5 B3 LDA &B3
ACE3 99 14 10 STA &1014,Y
ACE6 A5 B2 LDA &B2
ACE8 99 15 10 STA &1015,Y
ACEB 20 8D AE JSR RE8D
ACEE 4C 18 AC JMP RC18
.RCF1
ACF1 20 0F AD JSR RD0F ;ensure disc is double density
.RCF4
ACF4 20 85 B2 JSR S285 ;ensure disc write enabled
ACF7 D0 FB BNE RCF4 ;if write protected then try again
ACF9 20 B3 AE JSR REB3 ;clear pages &0E,&0F
ACFC A2 77 LDX #&77 ;point XY to "generating volumes" at &BE77
ACFE A0 B3 LDY #&B3
AD00 20 8D AD JSR RD8D ;print VDU sequence at XY
AD03 20 1D AF JSR RF1D ;write volume catalogues
AD06 20 41 AF JSR RF41 ;generate disc catalogue
AD09 20 DD A6 JSR R6DD ;write disc catalogue L3
AD0C 4C 44 AA JMP RA44 ;exit command on restart
.RD0F ;Ensure disc is double density
#if defined _DDOS316
AD0F 20 C4 B6 JSR S6C4 ;ensure disc is formatted
#elif defined _DDOS336
AD0F 20 C4 B6 JSR S6C4 ;ensure disc is formatted
#else
AD0F 20 C2 B6 JSR S6C2 ;ensure disc is formatted
#endif
AD12 2C E3 10 BIT &10E3 ;test density flag
AD15 70 20 BVS RD37 ;if single density
AD17 20 62 A3 JSR R362 ;then raise "must be double density" error.
AD1A EQUB &C9
AD1B EQUS "Disk must be double density"
AD36 EQUB &00
.RD37
AD37 60 RTS
.RD38 ;Print "DISK FORMATTER" heading
AD38 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
AD3B EQUB &1F ;move cursor to (0,2)
AD3C EQUB &00
AD3D EQUB &02
AD3E EQUB &FF
AD3F A2 02 LDX #&02
.RD41
AD41 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
AD44 EQUB &83 ;yellow alphanumerics
AD45 EQUB &8D ;double height
AD46 EQUS " D I S K F O R M A T T E R"
AD64 EQUB &0D
AD65 EQUB &0A
AD66 EQUB &FF
AD67 CA DEX
AD68 D0 D7 BNE RD41
AD6A 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
AD6D EQUB &0D ;CR + 4x LF
AD6E EQUB &0A
AD6F EQUB &0A
AD70 EQUB &0A
AD71 EQUB &0A
AD72 EQUB &FF
AD73 60 RTS
.RD74 ;Set display MODE 7
AD74 A9 07 LDA #&07
AD76 48 PHA
AD77 A9 16 LDA #&16
AD79 20 EE FF JSR &FFEE
AD7C 68 PLA
AD7D 4C EE FF JMP &FFEE
.RD80 ;Move cursor to (X,Y)
AD80 A9 1F LDA #&1F ;issue VDU 31 = PRINT TAB(X,Y)
AD82 20 EE FF JSR &FFEE
AD85 8A TXA ;send X coordinate to OSWRCH, 0=leftmost col
AD86 20 EE FF JSR &FFEE
AD89 98 TYA ;send Y coordinate to OSWRCH, 0=top row
AD8A 4C EE FF JMP &FFEE
.RD8D ;Print VDU sequence at XY
AD8D 86 B0 STX &B0 ;set up pointer at &B0,1 = XY
AD8F 84 B1 STY &B1
AD91 A0 00 LDY #&00 ;set offset to 0:
.RD93
AD93 B1 B0 LDA (&B0),Y ;get character of VDU sequence
AD95 C9 FF CMP #&FF ;is it the terminator byte?
AD97 F0 0A BEQ RDA3 ;if so then do not print, exit
AD99 20 EE FF JSR &FFEE ;else call OSWRCH to print it
AD9C C8 INY ;increment offset
AD9D D0 F4 BNE RD93 ;loop until offset overflows
AD9F E6 B1 INC &B1 ;then increment high byte of pointer
ADA1 D0 F0 BNE RD93 ;and loop until terminator byte reached
.RDA3
ADA3 60 RTS
.RDA4 ;Erase VDU sequence at XY
ADA4 86 B0 STX &B0 ;set up pointer at &B0,1 = XY
ADA6 84 B1 STY &B1
ADA8 A0 00 LDY #&00 ;set offset to 0:
.RDAA
ADAA B1 B0 LDA (&B0),Y ;get character of VDU sequence
ADAC C9 1F CMP #&1F ;is it 31 = TAB(X,Y)?
ADAE D0 10 BNE RDC0 ;if not then test for terminator byte
ADB0 20 CD AD JSR RDCD ;else VDU 31 and increment pointer
ADB3 B1 B0 LDA (&B0),Y ;send X coordinate to VDU (OSWRCH)
ADB5 20 CD AD JSR RDCD ;print character in A and increment pointer
ADB8 B1 B0 LDA (&B0),Y ;send Y coordinate to VDU (OSWRCH)
ADBA 20 CD AD JSR RDCD ;print character in A and increment pointer
ADBD 4C AA AD JMP RDAA ;and test next character
.RDC0
ADC0 C9 FF CMP #&FF ;is it &FF = the terminator byte?
ADC2 D0 01 BNE RDC5 ;if not then print space
ADC4 60 RTS ;else exit
.RDC5
ADC5 A9 20 LDA #&20 ;print a space
ADC7 20 CD AD JSR RDCD ;print character in A and increment pointer
ADCA 4C AA AD JMP RDAA ;and loop to test next character
.RDCD ;Print character in A and increment pointer
ADCD 20 EE FF JSR &FFEE ;call OSWRCH with character in A
ADD0 E6 B0 INC &B0 ;increment low byte of pointer at &B0
ADD2 D0 02 BNE RDD6 ;carry out to high byte
ADD4 E6 B1 INC &B1
.RDD6
ADD6 60 RTS
.RDD7 ;Clear row 23
ADD7 A2 00 LDX #&00 ;move cursor to (0,23)
ADD9 A0 17 LDY #&17
ADDB 20 80 AD JSR RD80 ;move cursor to (X,Y)
ADDE A2 28 LDX #&28 ;set X = 40, width of one MODE 7 row:
.RDE0 ;Print X spaces
ADE0 A9 20 LDA #&20 ;set A to ASCII value of space:
.RDE2 ;Print character X times
ADE2 20 EE FF JSR &FFEE ;call OSWRCH
ADE5 CA DEX ;decrement X
ADE6 D0 FA BNE RDE2 ;loop until X = 0, then exit
ADE8 60 RTS
.RDE9
ADE9 A2 06 LDX #&06
ADEB 18 CLC
ADEC A5 C1 LDA &C1
ADEE 69 09 ADC #&09
ADF0 A8 TAY
ADF1 4C 80 AD JMP RD80 ;move cursor to (X,Y)
.RDF4 ;Input number up to 5 digits
ADF4 A0 00 LDY #&00 ;start with no characters in line buffer
.RDF6
ADF6 20 AA B0 JSR S0AA ;get input character and acknowledge ESCAPE
ADF9 C9 0D CMP #&0D ;if user pressed RETURN
ADFB D0 02 BNE RDFF
ADFD 18 CLC ;then return C=0
ADFE 60 RTS
.RDFF
ADFF C9 7F CMP #&7F ;else if user pressed DELETE
AE01 D0 0C BNE RE0F
AE03 98 TYA ;then test number of characters entered
AE04 D0 02 BNE RE08 ;if no characters on line
AE06 38 SEC ;then return C=1
AE07 60 RTS
.RE08
AE08 20 25 AE JSR RE25 ;else backspace and erase last character
AE0B 88 DEY ;decrement number of characters entered
AE0C 4C F6 AD JMP RDF6 ;and loop
.RE0F
AE0F C0 05 CPY #&05 ;if 5 characters already entered
AE11 F0 E3 BEQ RDF6 ;then ignore latest, loop to read DEL/CR
AE13 C9 30 CMP #&30 ;else if character less than "0"
AE15 90 DF BCC RDF6 ;then ignore it
AE17 C9 3A CMP #&3A ;else if character more than "9"
AE19 B0 DB BCS RDF6 ;then ignore it
AE1B 20 EE FF JSR &FFEE ;else print input character
AE1E 99 31 10 STA &1031,Y ;store in line buffer
AE21 C8 INY ;increment number of characters entered
AE22 4C F6 AD JMP RDF6 ;and loop until user presses RETURN.
.RE25 ;Backspace and erase characters
AE25 20 2D AE JSR RE2D ;print DEL
AE28 A9 20 LDA #&20 ;print space:
AE2A 20 EE FF JSR &FFEE
.RE2D ;Print DEL
AE2D A9 7F LDA #&7F ;set A = ASCII value of DEL character
AE2F 4C EE FF JMP &FFEE ;call OSWRCH to print it and exit.
.RE32
AE32 38 SEC ;Convert ASCII digit to binary and validate
AE33 E9 30 SBC #&30 ;C=1 iff invalid
AE35 90 03 BCC RE3A
AE37 C9 0A CMP #&0A
AE39 60 RTS
.RE3A
AE3A 38 SEC
AE3B 60 RTS
.RE3C ;Divide word by word
AE3C A2 00 LDX #&00
.RE3E
AE3E A5 B1 LDA &B1 ;Compare dividend - divisor
AE40 C5 B3 CMP &B3
AE42 90 18 BCC RE5C
AE44 D0 06 BNE RE4C
AE46 A5 B0 LDA &B0
AE48 C5 B2 CMP &B2
AE4A 90 10 BCC RE5C ;if dividend < divisor
.RE4C
AE4C A5 B0 LDA &B0 ;then subtract dividend - divisor
AE4E E5 B2 SBC &B2
AE50 85 B0 STA &B0 ;ultimately leaving remainder
AE52 A5 B1 LDA &B1
AE54 E5 B3 SBC &B3
AE56 85 B1 STA &B1
AE58 E8 INX ;increment quotient in X
AE59 4C 3E AE JMP RE3E ;and loop as remainder > 0
.RE5C
AE5C 60 RTS
.RE5D ;Convert binary word to four decimal digits
AE5D A9 03 LDA #&03 ;set divisor = &03E8 = 1000
AE5F 85 B3 STA &B3
AE61 A9 E8 LDA #&E8
AE63 85 B2 STA &B2
AE65 20 3C AE JSR RE3C ;divide word by word
AE68 8E 2B 10 STX &102B ;store quotient as first digit (big-endian)
AE6B A9 00 LDA #&00 ;set divisor = &0064 = 100
AE6D 85 B3 STA &B3
AE6F A9 64 LDA #&64
AE71 85 B2 STA &B2
AE73 20 3C AE JSR RE3C ;divide word by word
AE76 8E 2C 10 STX &102C ;store quotient as second digit
AE79 A9 00 LDA #&00 ;set divisor = &000A = 10
AE7B 85 B3 STA &B3
AE7D A9 0A LDA #&0A
AE7F 85 B2 STA &B2
AE81 20 3C AE JSR RE3C ;divide word by word
AE84 8E 2D 10 STX &102D ;store quotient as third digit
AE87 A5 B0 LDA &B0 ;store remainder as fourth digit
AE89 8D 2E 10 STA &102E
AE8C 60 RTS
.RE8D
AE8D A5 C1 LDA &C1
AE8F 0A ASL A
AE90 A8 TAY
AE91 B9 14 10 LDA &1014,Y
AE94 85 B1 STA &B1
AE96 B9 15 10 LDA &1015,Y
AE99 85 B0 STA &B0
AE9B A5 B0 LDA &B0
AE9D 05 B1 ORA &B1
AE9F F0 11 BEQ REB2
AEA1 20 E9 AD JSR RDE9
AEA4 46 B1 LSR &B1
AEA6 66 B0 ROR &B0
AEA8 46 B1 LSR &B1
AEAA 66 B0 ROR &B0
AEAC 20 5D AE JSR RE5D ;convert binary word to four decimal digits
AEAF 20 66 B0 JSR S066 ;print four decimal digits, space-padded
.REB2
AEB2 60 RTS
.REB3 ;Clear pages &0E,&0F
AEB3 A9 00 LDA #&00
AEB5 A8 TAY
.REB6
AEB6 99 00 0E STA &0E00,Y
AEB9 99 00 0F STA &0F00,Y
AEBC C8 INY
AEBD D0 F7 BNE REB6
AEBF 60 RTS
.REC0
AEC0 A9 00 LDA #&00
AEC2 A0 0F LDY #&0F
.REC4
AEC4 99 14 10 STA &1014,Y
AEC7 88 DEY
AEC8 10 FA BPL REC4
AECA 60 RTS
.RECB
AECB A5 C4 LDA &C4
AECD 85 B2 STA &B2
AECF A5 C5 LDA &C5
AED1 85 B3 STA &B3
AED3 AD E1 10 LDA &10E1
AED6 85 B0 STA &B0
AED8 A9 00 LDA #&00
AEDA 85 B1 STA &B1
AEDC A2 04 LDX #&04
.REDE
AEDE 06 B0 ASL &B0
AEE0 26 B1 ROL &B1
AEE2 CA DEX
AEE3 D0 F9 BNE REDE
AEE5 A0 00 LDY #&00
.REE7
AEE7 20 1A B0 JSR S01A
AEEA 90 0D BCC REF9
AEEC A5 B3 LDA &B3
AEEE 99 14 10 STA &1014,Y
AEF1 A5 B2 LDA &B2
AEF3 99 15 10 STA &1015,Y
AEF6 4C 1C AF JMP RF1C
.REF9
AEF9 A5 B1 LDA &B1
AEFB 99 14 10 STA &1014,Y
AEFE A5 B0 LDA &B0
AF00 99 15 10 STA &1015,Y
AF03 38 SEC
AF04 A5 B2 LDA &B2
AF06 E5 B0 SBC &B0
AF08 85 B2 STA &B2
AF0A A5 B3 LDA &B3
AF0C E5 B1 SBC &B1
AF0E 85 B3 STA &B3
AF10 A5 B2 LDA &B2
AF12 05 B3 ORA &B3
AF14 F0 06 BEQ RF1C
AF16 C8 INY
AF17 C8 INY
AF18 C0 10 CPY #&10
AF1A D0 CB BNE REE7
.RF1C
AF1C 60 RTS
.RF1D ;Write volume catalogues
AF1D A0 00 LDY #&00 ;start at volume A
AF1F 84 BA STY &BA ;MSB of absolute LBA = 0
.RF21
AF21 B9 14 10 LDA &1014,Y ;test sector count of volume
AF24 19 15 10 ORA &1015,Y ;load MSB, or with LSB
AF27 F0 11 BEQ RF3A ;if no sectors assigned then skip cat write
AF29 B9 14 10 LDA &1014,Y ;else copy MSB sector count
AF2C 8D 06 0F STA &0F06 ;to catalogue
AF2F B9 15 10 LDA &1015,Y ;and copy MSB
AF32 8D 07 0F STA &0F07
AF35 84 BB STY &BB ;set LSB absolute LBA = 2 * volume letter
AF37 20 CE 92 JSR Q2CE ;write disc/volume catalogue L3
.RF3A
AF3A C8 INY ;advance volume letter by 1/sector by 2
AF3B C8 INY
AF3C C0 10 CPY #&10 ;have we initialised 8 volumes/16 sectors?
AF3E D0 E1 BNE RF21 ;if not then loop to init all volumes
AF40 60 RTS
.RF41 ;Generate disc catalogue
AF41 A9 20 LDA #&20 ;set version/configuration number = &20
AF43 8D 00 0E STA &0E00 ;indicating that sector count is big-endian
AF46 18 CLC
AF47 A5 C4 LDA &C4 ;get LSB of total sectors alloc. to volumes
AF49 69 12 ADC #&12 ;add 18 sectors for the catalogue track
AF4B 8D 02 0E STA &0E02 ;store LSB number of sectors on disc
AF4E A5 C5 LDA &C5 ;carry out to MSB
AF50 69 00 ADC #&00
AF52 8D 01 0E STA &0E01
AF55 A9 12 LDA #&12 ;18 sectors per track
AF57 8D 03 0E STA &0E03
AF5A A5 C0 LDA &C0 ;set number of tracks on disc
AF5C 8D 04 0E STA &0E04
AF5F A9 00 LDA #&00 ;mystery field (MSB no. tracks?), always 0
AF61 8D 05 0E STA &0E05
AF64 A9 01 LDA #&01 ;data area starts on track 1
AF66 85 BB STA &BB
AF68 A0 00 LDY #&00
.RF6A
AF6A B9 14 10 LDA &1014,Y ;get LSB requested sector count for volume
AF6D 85 B3 STA &B3 ;set as LSB of comparand
AF6F B9 15 10 LDA &1015,Y ;copy MSB
AF72 85 B2 STA &B2
AF74 A5 B2 LDA &B2 ;test number of requested sectors
AF76 05 B3 ORA &B3
AF78 F0 2A BEQ RFA4 ;if zero then volume absent, assign no tracks
AF7A A5 BB LDA &BB ;else set starting track of volume data area
AF7C 99 08 0E STA &0E08,Y
AF7F A9 00 LDA #&00 ;clear next byte (MSB track number?)
AF81 99 09 0E STA &0E09,Y
AF84 A2 00 LDX #&00 ;start with 0 tracks allocated to volume
AF86 86 B0 STX &B0 ;and 0 sectors allocated to volume:
AF88 86 B1 STX &B1
.RF8A
AF8A 20 1A B0 JSR S01A ;compare requested allocation with current
AF8D F0 0F BEQ RF9E ;if equal (blech!) then assign these tracks
AF8F E8 INX ;else add one track to allocation
AF90 18 CLC
AF91 A5 B0 LDA &B0 ;and add 18 sectors to allocation
AF93 69 12 ADC #&12
AF95 85 B0 STA &B0
AF97 90 02 BCC RF9B
AF99 E6 B1 INC &B1
.RF9B
AF9B 4C 8A AF JMP RF8A ;loop until allocation fulfilled
.RF9E
AF9E 18 CLC ;add number of tracks in X to starting track
AF9F 8A TXA
AFA0 65 BB ADC &BB
AFA2 85 BB STA &BB
.RFA4
AFA4 C8 INY ;skip to next volume entry
AFA5 C8 INY
AFA6 C0 10 CPY #&10 ;loop until tracks assigned to 8 volumes
AFA8 D0 C0 BNE RF6A
AFAA 60 RTS
.RFAB
AFAB 20 F5 AF JSR RFF5 ;copy volume allocations to workspace
AFAE 38 SEC
AFAF AD 02 0E LDA &0E02 ;get LSB number of sectors on disc
AFB2 E9 12 SBC #&12 ;subtract 18 sectors of catalogue track
AFB4 85 C4 STA &C4 ;set LSB total sectors allocated to volumes
AFB6 AD 01 0E LDA &0E01 ;borrow from MSB
AFB9 E9 00 SBC #&00
AFBB 85 C5 STA &C5
AFBD AD 04 0E LDA &0E04 ;get number of tracks on disc
AFC0 85 C0 STA &C0
AFC2 20 C0 AE JSR REC0
AFC5 A0 0E LDY #&0E ;start at volume H, cat. sector 14:
;Read volume sizes from the catalogue of each volume.
;This allows the size of each volume to be less than its allocation,
;in particular an allocation of 57 or more tracks may contain a volume
;of the maximum size, 1023 sectors (&3FF).
.RFC7
AFC7 98 TYA ;Y=2*volume
AFC8 4A LSR A ;A=volume
AFC9 AA TAX ;transfer to X for use as index
AFCA BD 06 10 LDA &1006,X ;look up number of tracks in volume
AFCD F0 1F BEQ RFEE ;if volume absent then skip
AFCF 84 BB STY &BB ;else set sector number = 2*volume
AFD1 E6 BB INC &BB ;add 1, point to 2nd sector of cat.
AFD3 A9 01 LDA #&01 ;256 bytes to transfer
AFD5 85 B1 STA &B1
AFD7 A9 00 LDA #&00
AFD9 85 B0 STA &B0
AFDB A9 00 LDA #&00 ;A=&00 (discarded)
AFDD 20 67 B4 JSR S467 ;transfer data
AFE0 AD 06 0E LDA &0E06 ;get boot option/top bits volume size
AFE3 29 03 AND #&03 ;extract MSB volume size
AFE5 99 14 10 STA &1014,Y ;set as MSB size of this volume
AFE8 AD 07 0E LDA &0E07 ;get LSB volume size from catalogue
AFEB 99 15 10 STA &1015,Y ;set as LSB size of this volume
.RFEE
AFEE 88 DEY ;proceed to previous volume
AFEF 88 DEY ;whose catalogue sector no. is two less
AFF0 10 D5 BPL RFC7 ;loop until all eight volumes read
#if defined _DDOS316
AFF2 4C 4B B7 JMP S74B ;exit (jump to RTS)
#elif defined _DDOS336
AFF2 4C 4B B7 JMP S74B ;exit (jump to RTS)
#else
AFF2 4C 49 B7 JMP S749 ;exit (jump to RTS)
#endif
.RFF5 ;Copy volume allocations to workspace
AFF5 20 D9 A6 JSR R6D9 ;load disc catalogue L3
AFF8 A0 0E LDY #&0E
AFFA A2 07 LDX #&07
.RFFC
AFFC B9 08 0E LDA &0E08,Y
AFFF 9D 06 10 STA &1006,X
B002 88 DEY
B003 88 DEY
B004 CA DEX
B005 10 F5 BPL RFFC
B007 60 RTS
.S008
B008 18 CLC
B009 A5 B2 LDA &B2
B00B 65 B4 ADC &B4
B00D 85 B2 STA &B2
B00F A5 B3 LDA &B3
B011 65 B5 ADC &B5
B013 85 B3 STA &B3
B015 C6 B0 DEC &B0
B017 D0 EF BNE S008
B019 60 RTS
.S01A
B01A A5 B1 LDA &B1
B01C C5 B3 CMP &B3
B01E D0 04 BNE S024
B020 A5 B0 LDA &B0
B022 C5 B2 CMP &B2
.S024
B024 60 RTS
.S025
B025 AC E1 10 LDY &10E1
B028 A9 00 LDA #&00
B02A 85 C4 STA &C4
B02C 85 C5 STA &C5
.S02E
B02E 18 CLC
B02F A5 B0 LDA &B0
B031 65 C4 ADC &C4
B033 85 C4 STA &C4
B035 90 02 BCC S039
B037 E6 C5 INC &C5
.S039
B039 88 DEY
B03A D0 F2 BNE S02E
B03C 60 RTS
.S03D
B03D A0 00 LDY #&00
B03F 84 B0 STY &B0
B041 84 B1 STY &B1
.S043
B043 18 CLC
B044 A5 B0 LDA &B0
B046 79 15 10 ADC &1015,Y
B049 85 B0 STA &B0
B04B A5 B1 LDA &B1
B04D 79 14 10 ADC &1014,Y
B050 85 B1 STA &B1
B052 C8 INY
B053 C8 INY
B054 C0 10 CPY #&10
B056 D0 EB BNE S043
B058 38 SEC
B059 A5 C4 LDA &C4
B05B E5 B0 SBC &B0
B05D 85 C2 STA &C2
B05F A5 C5 LDA &C5
B061 E5 B1 SBC &B1
B063 85 C3 STA &C3
B065 60 RTS
.S066 ;Print four decimal digits, space-padded
B066 A0 FF LDY #&FF ;set Y=&FF going to 0, start at first digit
.S068 ;Print decimal digits, space-padded
B068 38 SEC ;set C=1 pad with spaces
.S069
B069 C8 INY
B06A B9 2B 10 LDA &102B,Y ;get digit
B06D D0 0D BNE S07C ;if >0 then print it
B06F 90 0B BCC S07C ;if a digit was printed then print the rest
B071 C0 03 CPY #&03 ;else if at the fourth digit
B073 F0 07 BEQ S07C ;then always print it
B075 A9 20 LDA #&20 ;else print a space
B077 20 EE FF JSR &FFEE ;call OSWRCH
B07A D0 EC BNE S068 ;and print the rest; [BUG] Z undefined
.S07C
B07C 18 CLC ;c=0 print all subsequent digits
B07D 69 30 ADC #&30 ;convert binary to ASCII "0".."9"
B07F 20 EE FF JSR &FFEE ;call OSWRCH
B082 C0 03 CPY #&03 ;if fewer than 4 digits printed
B084 D0 E3 BNE S069 ;then loop to print the rest
B086 60 RTS ;else exit
.S087 ;Get printable input character
B087 20 AA B0 JSR S0AA ;get input character and acknowledge ESCAPE
B08A C9 30 CMP #&30 ;is ASCII value less than that of "0"?
B08C 90 F9 BCC S087 ;if so then discard, get another character
B08E C9 5B CMP #&5B ;else is ASCII value higher than "Z"?
B090 B0 F5 BCS S087 ;if so then discard, get another character
B092 48 PHA ;else save input character
B093 20 EE FF JSR &FFEE ;call OSWRCH to print it:
.S096
B096 20 AA B0 JSR S0AA ;get input character and acknowledge ESCAPE
B099 C9 0D CMP #&0D ;is it CR?
B09B D0 02 BNE S09F ;if not then test for DEL
B09D 68 PLA ;else restore first character and exit
B09E 60 RTS
.S09F
B09F C9 7F CMP #&7F ;was DELETE key pressed?
B0A1 D0 F3 BNE S096 ;if neither CR or DEL then get another
B0A3 68 PLA ;else discard first character
B0A4 20 25 AE JSR RE25 ;backspace and erase characters
B0A7 4C 87 B0 JMP S087 ;and loop to get another character.
.S0AA ;Get input character and acknowledge ESCAPE
B0AA 20 E0 FF JSR &FFE0 ;call OSRDCH
B0AD B0 01 BCS S0B0 ;if C=1 then ESCAPE pressed, acknowledge
B0AF 60 RTS ;else return character in A
.S0B0
B0B0 C9 1B CMP #&1B ;test if returned character is ESCAPE
B0B2 F0 01 BEQ S0B5 ;(what if ESCAPE character was changed?)
B0B4 60 RTS ;if unequal then return, else:
.S0B5
B0B5 20 58 A4 JSR R458 ;acknowledge ESCAPE condition
B0B8 20 A7 A7 JSR R7A7 ;release NMI
B0BB AE 10 10 LDX &1010 ;restore stack pointer from &1010
B0BE 9A TXS
B0BF 6C 11 10 JMP (&1011) ;jump to action address
.S0C2 ;Briefly display error indication
B0C2 A9 07 LDA #&07
B0C4 20 EE FF JSR &FFEE ;print BEL = make a short beep
B0C7 A2 C4 LDX #&C4 ;point XY to "E R R O R" at &B3C4
B0C9 A0 B3 LDY #&B3
B0CB 8A TXA ;save XY
B0CC 48 PHA
B0CD 98 TYA
B0CE 48 PHA
B0CF A9 86 LDA #&86
B0D1 20 F4 FF JSR &FFF4 ;call OSBYTE &86 = read cursor pos'n
B0D4 8E 26 10 STX &1026 ;save POS in workspace
B0D7 8C CF 10 STY &10CF ;save VPOS in workspace
B0DA 68 PLA ;restore pointer to "E R R O R"
B0DB A8 TAY
B0DC 68 PLA
B0DD AA TAX
B0DE 20 8D AD JSR RD8D ;print VDU sequence at XY
B0E1 AE 26 10 LDX &1026 ;restore previous cursor position
B0E4 AC CF 10 LDY &10CF
B0E7 20 80 AD JSR RD80 ;move cursor to (X,Y)
B0EA A9 05 LDA #&05 ;wait 822 milliseconds + interrupts:
B0EC 85 B0 STA &B0 ;clear X and Y for use as counters
B0EE A2 00 LDX #&00
B0F0 A0 00 LDY #&00
.S0F2
B0F2 88 DEY
B0F3 D0 FD BNE S0F2
B0F5 CA DEX ;this point reached every 640 microseconds
B0F6 D0 FA BNE S0F2
B0F8 C6 B0 DEC &B0 ;this point reached every 164 milliseconds
B0FA D0 F6 BNE S0F2
B0FC 20 8B B1 JSR S18B ;clear rows 20..22
B0FF AE 26 10 LDX &1026 ;restore previous cursor position
B102 AC CF 10 LDY &10CF
B105 20 80 AD JSR RD80 ;move cursor to (X,Y) and exit
B108 60 RTS
.S109 ;Convert ASCII numeric to unsigned word
B109 A2 00 LDX #&00
B10B 86 B0 STX &B0
B10D 86 B1 STX &B1
.S10F
B10F BD 31 10 LDA &1031,X ;get character of string
B112 20 32 AE JSR RE32 ;convert ASCII digit to binary and validate
B115 B0 2B BCS S142 ;if invalid return with digits added so far
B117 48 PHA ;else &B0,1 = &B0,1 * 10 + A:
B118 A5 B1 LDA &B1 ;save current value of &B1
B11A 48 PHA
B11B A5 B0 LDA &B0 ;save current value of &B0
B11D 06 B0 ASL &B0 ;shift &B0,&B1 left twice
B11F 26 B1 ROL &B1 ;to multiply by 4
B121 06 B0 ASL &B0
B123 26 B1 ROL &B1
B125 18 CLC
B126 65 B0 ADC &B0 ;add old &B0,&B1 to it making 5x
B128 85 B0 STA &B0
B12A 68 PLA
B12B 65 B1 ADC &B1
B12D 85 B1 STA &B1
B12F 06 B0 ASL &B0 ;shift &B0,&B1 left once to double it
B131 26 B1 ROL &B1 ;making 10x
B133 18 CLC
B134 68 PLA ;add saved value of A to &B0
B135 65 B0 ADC &B0
B137 85 B0 STA &B0
B139 90 02 BCC S13D ;and carry out to &B1.
B13B E6 B1 INC &B1
.S13D
B13D E8 INX
B13E 88 DEY
B13F D0 CE BNE S10F
B141 18 CLC
.S142
B142 60 RTS
.S143
B143 20 8B B1 JSR S18B ;clear rows 20..22
B146 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
B149 EQUB &1F ;move cursor to (5,23)
B14A EQUB &05
B14B EQUB &17
B14C EQUB &88 ;flashing text
B14D EQUB &83 ;yellow alphanumerics
B14E EQUS "F O R M A T E R R O R"
B165 EQUB &FF ;terminator byte
B166 60 RTS
.S167 ;Print "VERIFY ERROR"
B167 20 8B B1 JSR S18B ;clear rows 20..22
B16A 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
B16D EQUB &1F ;move cursor to (5,23)
B16E EQUB &05
B16F EQUB &17
B170 EQUB &88 ;flashing text
B171 EQUB &83 ;yellow alphanumerics
B172 EQUS "V E R I F Y E R R O R"
B189 EQUB &FF ;terminator byte
B18A 60 RTS
.S18B ;Clear rows 20..22
B18B A2 00 LDX #&00 ;move cursor to (0,20)
B18D A0 14 LDY #&14
B18F 20 80 AD JSR RD80 ;move cursor to (X,Y)
B192 A2 78 LDX #&78 ;print 120 spaces and exit
B194 4C E0 AD JMP RDE0 ;print X spaces
.S197 ;Prompt user and start format
B197 A2 34 LDX #&34 ;point XY at "READY TO FORMAT" heading
B199 A0 B3 LDY #&B3 ;at &B334
B19B 20 8D AD JSR RD8D ;print VDU sequence at XY
B19E 20 87 B0 JSR S087 ;get printable input character
B1A1 C9 46 CMP #&46 ;is it capital F?
B1A3 D0 F2 BNE S197 ;if not then reprint heading and try again
B1A5 20 85 B2 JSR S285 ;ensure disc write enabled
B1A8 D0 ED BNE S197 ;if write protected then try again
B1AA 20 D2 A3 JSR R3D2 ;else print VDU sequence immediate
B1AD EQUB &0C ;clear screen
B1AE EQUB &1F ;move cursor to (0,20)
B1AF EQUB &00
B1B0 EQUB &14
B1B1 EQUB &88 ;flashing text
B1B2 EQUB &83 ;yellow alphanumerics
B1B3 EQUS "Please wait while formatting disk"
B1D4 EQUB &FF ;terminator byte
#if defined _DDOS316
B1D5 20 7E B6 JSR S67E
#elif defined _DDOS336
B1D5 20 7E B6 JSR S67E
#else
B1D5 20 7C B6 JSR S67C ;recalibrate drive (seek track 0)
#endif
B1D8 A9 00 LDA #&00
B1DA 85 BA STA &BA
B1DC A9 02 LDA #&02
B1DE 85 B9 STA &B9
B1E0 85 BB STA &BB
#if defined _DDOS316
B1E2 20 2B B8 JSR S82B
#elif defined _DDOS336
B1E2 20 2B B8 JSR S82B
#else
B1E2 20 4E B8 JSR S84E
#endif
.S1E5
B1E5 38 SEC
B1E6 A5 B9 LDA &B9
B1E8 E9 02 SBC #&02
B1EA B0 03 BCS S1EF
B1EC 6D E1 10 ADC &10E1
.S1EF
B1EF 85 B9 STA &B9
#if defined _DDOS316
B1F1 20 91 B6 JSR S691
#elif defined _DDOS336
B1F1 20 91 B6 JSR S691
#else
B1F1 20 8F B6 JSR S68F ;seek logical track
#endif
B1F4 A9 03 LDA #&03 ;make three attempts (outer)
B1F6 8D 2A 10 STA &102A ;set attempt counter
.S1F9
B1F9 20 40 A4 JSR R440
B1FC 20 53 B2 JSR S253 ;print track number in table
B1FF A0 06 LDY #&06 ;erase next 6 characters
B201 20 08 B3 JSR S308 ;erase Y characters ahead of cursor
B204 A5 B9 LDA &B9
B206 85 BB STA &BB
#if defined _DDOS316
B208 20 2B B8 JSR S82B
#elif defined _DDOS336
B208 20 2B B8 JSR S82B
#else
B208 20 4E B8 JSR S84E
#endif
B20B F0 0E BEQ S21B
B20D CE 2A 10 DEC &102A
B210 D0 E7 BNE S1F9
B212 20 43 B1 JSR S143 ;else print "FORMAT ERROR"
B215 A9 02 LDA #&02
B217 8D 13 10 STA &1013 ;set return code = 2, format failed
B21A 60 RTS
.S21B
B21B 20 28 AB JSR RB28 ;verify track with display
B21E F0 0E BEQ S22E ;if succeeded then verify next track
B220 CE 2A 10 DEC &102A ;else decrement attempt counter
B223 D0 D4 BNE S1F9 ;if attempts remaining then try again
B225 20 67 B1 JSR S167 ;else print "VERIFY ERROR"
B228 A9 03 LDA #&03
B22A 8D 13 10 STA &1013 ;set return code = 3, verify failed
B22D 60 RTS
.S22E
B22E E6 BA INC &BA
B230 A5 BA LDA &BA
B232 C5 C0 CMP &C0
B234 B0 03 BCS S239
B236 4C E5 B1 JMP S1E5
.S239
B239 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
B23C EQUB &1F ;move cursor to (8,23)
B23D EQUB &08
B23E EQUB &17
B23F EQUB &83 ;yellow alphanumerics
B240 EQUS "Format complete"
B24F EQUB &0D
B250 EQUB &0A
B251 EQUB &FF
B252 60 RTS
.S253 ;Print track number in table
B253 A9 00 LDA #&00 ;set column to 0
B255 85 B1 STA &B1
B257 A5 BA LDA &BA ;copy track number as row number
B259 85 B0 STA &B0
.S25B
B25B 38 SEC ;subtract 20 from row number
B25C A5 B0 LDA &B0
B25E E9 14 SBC #&14
B260 90 0C BCC S26E ;if underflow then keep current row
B262 85 B0 STA &B0 ;else set as new row number
B264 18 CLC ;add 10 to column
B265 A5 B1 LDA &B1
B267 69 0A ADC #&0A
B269 85 B1 STA &B1
B26B 4C 5B B2 JMP S25B ;and loop until row < 20
.S26E
B26E A6 B1 LDX &B1 ;set X = column
B270 A4 B0 LDY &B0 ;set Y = row
B272 20 80 AD JSR RD80 ;move cursor to (X,Y)
B275 A5 BA LDA &BA ;copy track number as low byte of word
B277 85 B0 STA &B0
B279 A9 00 LDA #&00 ;clear high byte of word
B27B 85 B1 STA &B1
B27D 20 5D AE JSR RE5D ;convert binary word to four decimal digits
B280 A0 01 LDY #&01 ;set Y=1 print 3 - Y = 2 digits
B282 4C 68 B0 JMP S068 ;print decimal digits, space-padded
.S285 ;Ensure disc write enabled
B285 20 E2 A7 JSR R7E2 ;test write protect state of current drive
B288 F0 59 BEQ S2E3 ;if write enabled then return
B28A 20 D2 A3 JSR R3D2 ;else print VDU sequence immediate
B28D EQUB &1F ;move cursor to (0,20)
B28E EQUB &00
B28F EQUB &14
B290 EQUB &88
B291 EQUB &83 ;yellow alphanumerics
B292 EQUS " *** Disk write protected ***"
B2B1 EQUB &0D
B2B2 EQUB &0A
B2B3 EQUB &83 ;yellow alphanumerics
B2B4 EQUS "Remove write protect label from disk"
B2D8 EQUB &0D
B2D9 EQUB &0A
B2DA EQUB &FF
B2DB 20 E4 B2 JSR S2E4 ;prompt for keypress
B2DE 20 8B B1 JSR S18B ;clear rows 20..22
B2E1 A9 FF LDA #&FF
.S2E3
B2E3 60 RTS
.S2E4 ;Prompt for keypress
B2E4 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
B2E7 EQUB &0D
B2E8 EQUS "Press any key to continue"
B301 EQUB &FF
B302 20 AA B0 JSR S0AA ;get input character and acknowledge ESCAPE
B305 4C 8B B1 JMP S18B ;clear rows 20..22 and exit
.S308 ;Erase Y characters ahead of cursor
B308 98 TYA
B309 48 PHA
B30A 20 DA 88 JSR P8DA ;print number of spaces in Y
B30D 68 PLA
B30E A8 TAY
.S30F
B30F A9 7F LDA #&7F
B311 20 EE FF JSR &FFEE
B314 88 DEY
B315 D0 F8 BNE S30F
B317 60 RTS
B318 EQUB &1F ;move cursor to (0,23)
B319 EQUB &00
B31A EQUB &17
B31B EQUS "Volume : "
B32B EQUB &7F
B32C EQUB &7F
B32D EQUB &7F
B32E EQUB &7F
B32F EQUB &7F
B330 EQUB &7F
B331 EQUB &7F
B332 EQUB &7F
B333 EQUB &FF
B334 EQUB &16 ;set display MODE 7
B335 EQUB &07
B336 EQUB &0A
B337 EQUB &0A
B338 EQUB &0A
B339 EQUB &83 ;yellow alphanumerics
B33A EQUS " R E A D Y T O F O R M A T"
B35B EQUB &0D
B35C EQUB &0A
B35D EQUB &0A
B35E EQUB &0A
B35F EQUB &83 ;yellow alphanumerics
B360 EQUS "Press F(ret) to start "
B376 EQUB &FF
B377 EQUB &1F ;move cursor to (0,20)
B378 EQUB &00
B379 EQUB &14
B37A EQUB &88
B37B EQUB &83 ;yellow alphanumerics
B37C EQUS "Please wait while generating volumes"
B3A0 EQUB &FF
B3A1 EQUB &1F ;move cursor to (2,14)
B3A2 EQUB &02
B3A3 EQUB &0E
B3A4 EQUB &83 ;yellow alphanumerics
B3A5 EQUS "VOLUME GENERATION COMPLETE"
B3BF EQUB &0D
B3C0 EQUB &0A
B3C1 EQUB &0A
B3C2 EQUB &0A
B3C3 EQUB &FF
B3C4 EQUB &1F ;move cursor to (4,20)
B3C5 EQUB &04
B3C6 EQUB &14
B3C7 EQUB &88 ;flashing text
B3C8 EQUB &83 ;yellow alphanumerics
B3C9 EQUS " E R R O R"
B3D6 EQUB &FF ;terminator byte
;*DENSITY
B3D7 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
B3DA 98 TYA ;transfer command line offset to A
B3DB A2 E6 LDX #&E6 ;point XY to keyword table at &B3E6
B3DD A0 B3 LDY #&B3
B3DF 20 C7 8E JSR PEC7 ;search for keyword in table
B3E2 A2 03 LDX #&03 ;density flag goes to &10E3
B3E4 D0 28 BNE S40E ;jump to action address
;*DENSITY keyword table
B3E6 EQUS "SINGLE"
B3EC EQUW &B4,&28
B3EE EQUB &00
B3EF EQUS "DOUBLE"
B3F5 EQUW &B4,&25
B3F7 EQUB &00
B3F8 EQUS "AUTO"
B3FC EQUW &B4,&2B
B3FE EQUB &00 ;unused syntax byte
B3FF EQUW &94,&F8 ;wrong keyword, "Bad command" &94F8
;*4080
B401 20 0E A0 JSR R00E ;call GSINIT with C=0 and reject empty arg
B404 98 TYA ;transfer command line offset to A
B405 A2 11 LDX #&11 ;point XY to keyword table at &B411
B407 A0 B4 LDY #&B4
B409 20 C7 8E JSR PEC7 ;search for keyword in table
B40C A2 00 LDX #&00 ;stepping flag goes to &10E0
.S40E
#if defined _DDOS357
B40E 4C C9 80 JMP P0C9 ;jump to action address
#else
B40E 4C CC 80 JMP P0CC ;jump to action address
#endif
;*4080 keyword table
B411 EQUS "ON"
B413 EQUW &B4,&25
B415 EQUB &00
B416 EQUS "OFF"
B419 EQUW &B4,&28
B41B EQUB &00
B41C EQUS "AUTO"
B420 EQUW &B4,&2B
B422 EQUB &00 ;unused syntax byte
B423 EQUW &94,&F8 ;wrong keyword, "Bad command" &94F8
B425 A9 40 LDA #&40 ;*4080 ON *DENSITY DOUBLE
B427 AC A9 00 LDY &00A9 ;*4080 OFF *DENSITY SINGLE B428=LDA #&00
B42A AC A9 80 LDY &80A9 ;*4080 AUTO *DENSITY AUTO B42B=LDA #&80
B42D 9D E0 10 STA &10E0,X ;to &10E0 or &10E3
B430 60 RTS
;*RAMINIT
B431 BA TSX ;have A=0 returned on exit, claim call
B432 A9 00 LDA #&00
B434 9D 05 01 STA &0105,X
B437 20 29 A3 JSR R329 ;save XY (inner)
B43A 20 C1 A7 JSR R7C1 ;claim NMI
B43D A9 00 LDA #&00 ;destination LBA = &0000, start of RAM disc
B43F 85 BA STA &BA
B441 85 BB STA &BB
B443 20 B3 AE JSR REB3 ;clear pages &0E,&0F
#if defined _RAMINIT64K
B446 A9 01 LDA #&01 ;set volume size in catalogue = 64 KiB
#elif defined _RAMINIT256K
B446 A9 03 LDA #&03 ;set volume size in catalogue = 256 KiB
#else
B446 A9 02 LDA #&02 ;set volume size in catalogue = 128 KiB
#endif
B448 8D 06 0F STA &0F06
#if defined _RAMINIT256K
B44B A9 FF LDA #&FF
#else
B44B A9 00 LDA #&00
#endif
B44D 8D 07 0F STA &0F07
B450 A9 02 LDA #&02 ;set transfer size in &A0,1 = 512 bytes
B452 85 A1 STA &A1
B454 A9 00 LDA #&00
B456 85 A0 STA &A0
B458 A9 01 LDA #&01 ;data transfer call &01 = write data
B45A 8D 00 10 STA &1000 ;set data transfer call number
B45D 20 ED 92 JSR Q2ED ;set data pointer to &0E00
B460 20 70 B4 JSR S470 ;transfer data to paged RAM
B463 20 A7 A7 JSR R7A7 ;release NMI
B466 60 RTS
.S467 ;Transfer data L2
B467 A5 CF LDA &CF ;get current volume
B469 29 0C AND #&0C ;if not on physical drive 0..3
B46B D0 03 BNE S470 ;then transfer data to paged RAM
#if defined _DDOS316
B46D 4C 5F B7 JMP S75F ;else transfer data to disc L2
#elif defined _DDOS336
B46D 4C 5F B7 JMP S75F ;else transfer data to disc L2
#else
B46D 4C 5D B7 JMP S75D ;else transfer data to disc L2
#endif
.S470 ;Transfer data to paged RAM
B470 20 29 A3 JSR R329 ;save XY
B473 A5 A2 LDA &A2 ;save &A2..5
B475 48 PHA
B476 A5 A3 LDA &A3
B478 48 PHA
B479 A5 A4 LDA &A4
B47B 48 PHA
B47C A5 A5 LDA &A5
B47E 48 PHA
B47F A0 54 LDY #&54 ;copy 85 bytes:
.S481
B481 B9 11 B5 LDA &B511,Y ;copy RAM transfer code from &B511..65
B484 99 00 0D STA &0D00,Y ;to NMI handler area at &0D00..54
B487 88 DEY ;loop until 85 bytes copied
B488 10 F7 BPL S481
B48A AD 01 10 LDA &1001 ;copy *SROM slot number
B48D 85 A3 STA &A3 ;to NMI zero page area
B48F A5 BA LDA &BA ;copy starting LBA HIGH byte
B491 85 A5 STA &A5 ;to &A5
B493 A5 BB LDA &BB ;copy starting LBA LOW byte
B495 85 A4 STA &A4 ;to &A4
B497 A5 A0 LDA &A0 ;if transfer includes a partial page
B499 F0 02 BEQ S49D
B49B E6 A1 INC &A1 ;then round up number of pages
.S49D
B49D AD 00 10 LDA &1000 ;if data transfer call is not 0 = read data
B4A0 D0 16 BNE S4B8 ;then modify RAM transfer code for write
B4A2 A5 A6 LDA &A6 ;else paste user memory address at &0D14,5
B4A4 8D 14 0D STA &0D14
B4A7 A5 A7 LDA &A7
B4A9 8D 15 0D STA &0D15
B4AC AD D5 10 LDA &10D5 ;test Tube transfer flag
#if defined _RAMBUGFIX
B4AF F0 49 BEQ S4FA ;if b7=0 then an I/O transfer, branch
#else
B4AF F0 4C BEQ S4FD ;if b7=0 then an I/O transfer, branch
#endif
B4B1 A9 8D LDA #&8D ;else instruction at &0D13 = STA &FEE5
B4B3 A0 08 LDY #&08
B4B5 4C DF B4 JMP S4DF ;modify RAM transfer code for Tube.
.S4B8 ;Modify RAM transfer code for write
B4B8 A9 15 LDA #&15 ;instruction at &0D51 = STA &0D15
B4BA 8D 52 0D STA &0D52
B4BD A9 A3 LDA #&A3 ;instruction at &0D06 = LDX &A3
B4BF 8D 07 0D STA &0D07
B4C2 A9 A2 LDA #&A2 ;instruction at &0D0E = LDX &A2
B4C4 8D 0F 0D STA &0D0F
B4C7 A5 A6 LDA &A6 ;paste user memory address at &0D0C,D
B4C9 8D 0C 0D STA &0D0C
B4CC A5 A7 LDA &A7
B4CE 8D 0D 0D STA &0D0D
B4D1 A9 0D LDA #&0D ;instruction at &0D19 = INC &0D0D
B4D3 8D 1A 0D STA &0D1A
B4D6 AD D5 10 LDA &10D5 ;test Tube transfer flag
#if defined _RAMBUGFIX
B4D9 F0 1F BEQ S4FA ;if b7=0 then an I/O transfer, branch
#else
B4D9 F0 22 BEQ S4FD ;if b7=0 then an I/O transfer, branch
#endif
B4DB A9 AD LDA #&AD ;else instruction at &0D0B = LDA &FEE5
B4DD A0 00 LDY #&00 ;fall through:
.S4DF ;Modify RAM transfer code for Tube
B4DF 99 0B 0D STA &0D0B,Y ;store opcode LDA abs at &D0B/STA abs at &D13
#if defined _RAMBUGFIX
B4E2 EA NOP ;no operation
#else
B4E2 C8 INY ;increment offset - d'oh! [BUG]
#endif
B4E3 A9 E5 LDA #&E5 ;store address of Tube FIFO 3, &FEE5
B4E5 99 0C 0D STA &0D0C,Y ;at &0D0D,E or &0D15,6
B4E8 A9 FE LDA #&FE
B4EA 99 0D 0D STA &0D0D,Y
B4ED A9 EA LDA #&EA ;instructions at &0D19,&0D1A,&0D1B = NOP
B4EF 8D 19 0D STA &0D19 ;which was INC &0D15/INC &0D0D
B4F2 8D 1A 0D STA &0D1A
B4F5 8D 1B 0D STA &0D1B
#if defined _RAMBUGFIX
B4F8 49 00 EOR #&00 ;no operation
.S4FA
B4FA A0 00 LDY #&00 ;starting offset = &00
B4FC 20 36 0D JSR &0D36 ;compute source RAM slot number
B4FF 20 03 0D JSR &0D03 ;do transfer to/from paged RAM
#else
B4F8 A9 60 LDA #&60 ;instruction at &0D4B = RTS
B4FA 8D 4B 0D STA &0D4B ;disable paste high byte of source address
.S4FD
B4FD A0 00 LDY #&00 ;starting offset = &00
B4FF 20 00 0D JSR &0D00 ;do transfer to/from paged RAM
#endif
B502 68 PLA ;restore &A2..5 from stack
B503 85 A5 STA &A5
B505 68 PLA
B506 85 A4 STA &A4
B508 68 PLA
B509 85 A3 STA &A3
B50B 68 PLA
B50C 85 A2 STA &A2
B50E A9 00 LDA #&00 ;fake WD1770 status = 0, succeeded.
B510 60 RTS
;Paged RAM transfer code copied to &0D00
#if defined _RAMBUGFIX
B511 40 RTI ;ignore spurious interrupts
#else
B511 20 36 0D JSR &0D36 ;compute source RAM slot number
#endif
B514 20 4B 0D JSR &0D4B ;paste high byte of source address
.S517
B517 A6 A2 LDX &A2
B519 8E 30 FE STX &FE30
B51C B9 00 FF LDA &FF00,Y ;high byte of source address pasted to &0D0D
B51F A6 A3 LDX &A3
B521 8E 30 FE STX &FE30
B524 99 00 FF STA &FF00,Y ;high byte of dest. address pasted to &0D15
B527 C8 INY
B528 D0 0F BNE S539
B52A EE 15 0D INC &0D15 ;increment high byte of STA address
B52D E6 A4 INC &A4
B52F D0 02 BNE S533
B531 E6 A5 INC &A5
.S533
B533 20 36 0D JSR &0D36 ;compute source RAM slot number
B536 20 4B 0D JSR &0D4B ;paste high byte of source address
.S539
B539 C6 A0 DEC &A0 ;decrement byte count
B53B D0 DA BNE S517 ;loop until all bytes transferred
B53D C6 A1 DEC &A1
B53F D0 D6 BNE S517
B541 A5 F4 LDA &F4 ;page DDOS ROM back in
B543 8D 30 FE STA &FE30
B546 60 RTS ;return
#if defined _BMEM
B547 A5 A5 LDA &A5
B549 4A LSR A
B54A A5 A4 LDA &A4
B54C 6A ROR A
B54D 4A LSR A
B54E 4A LSR A
B54F 4A LSR A ;...Habcd
B550 C9 10 CMP #&10
B552 29 0C AND #&0C
B554 69 00 ADC #&00 ;....ab.H
B556 49 03 EOR #&03 ;37BF26AE
B558 85 A2 STA &A2
B55A 60 RTS
#elif defined _TWOMEG
B547 A5 A5 LDA &A5
B549 4A LSR A
B54A A5 A4 LDA &A4 ;abcdefgh H
B54C 2A ROL A
B54D 2A ROL A
B54E 2A ROL A ;defghHab c
B54F 29 07 AND #&07
B551 18 CLC ;.....Hab
B552 69 04 ADC #&04 ;....H~ab
B554 29 0B AND #&0B ;....H.ab
B556 49 04 EOR #&04 ;4567CDEF
B558 85 A2 STA &A2
B55A 60 RTS
#elif defined _PLUGIN
B547 A5 A5 LDA &A5
B549 4A LSR A
B54A A5 A4 LDA &A4 ;abcdefgh H
B54C 2A ROL A
B54D 2A ROL A ;cdefghHa b
B54E 29 03 AND #&03
B550 90 02 BCC S554
B552 49 04 EOR #&04 ;.....bHa
.S554
B554 49 00 EOR #&00 ;04152637 or &03 to go right-to-left
B556 85 A2 STA &A2
B558 60 RTS
#elif defined _PLUGIN2
B547 A5 A5 LDA &A5
B549 4A LSR A
B54A A5 A4 LDA &A4
B54C 2A ROL A
B54D 29 81 AND #&81 ;b......H a
B54F 10 02 BPL S553
B551 49 84 EOR #&84 ;.....b.H a
.S553
B553 90 02 BCC S557
B555 49 02 EOR #&02 ;.....baH or &03 for middle/end sockets
.S557
B557 49 00 EOR #&00 ;04261537 or slot no. of first plugin
B559 85 A2 STA &A2
B55B 60 RTS
#elif defined _MASTER
B547 A5 A5 LDA &A5
B549 4A LSR A
B54A A5 A4 LDA &A4 ;abcdefgh H
B54C 2A ROL A
B54D 2A ROL A
B54E 2A ROL A ;defghHab c
B54F 29 07 AND #&07 ;.....Hab
B551 49 04 EOR #&04 ;45670123
B553 85 A2 STA &A2
B555 60 RTS
#else
B547 A5 A5 LDA &A5 ;0D36
B549 85 A2 STA &A2 ;copy bits of &A5: ABCDEFGH
B54B A5 A4 LDA &A4 ;load bits of &A4: abcdefgh
B54D 29 C0 AND #&C0 ;mask b7,6: ab......
B54F 46 A2 LSR &A2
B551 6A ROR A ;a=Hab....., &A2=.ABCDEFG
B552 46 A2 LSR &A2
B554 6A ROR A ;a=GHab...., &A2=..ABCDEF
B555 69 10 ADC #&10 ;c=0; skip slot &0E, reserved for paged ROM
B557 09 0E ORA #&0E ;a=GHab111. adjusted
B559 85 A2 STA &A2 ;save result as source RAM 'slot' number
B55B 60 RTS
#endif
B55C A5 A4 LDA &A4 ;0D4B
B55E 29 3F AND #&3F ;take high byte of source address
B560 09 80 ORA #&80 ;confine to paged ROM address space &80..BF
B562 8D 0D 0D STA &0D0D ;paste in high byte of LDA &FF00,Y instr.
B565 60 RTS
;*FDCSTAT
B566 BA TSX
B567 A9 00 LDA #&00
B569 9D 05 01 STA &0105,X
B56C 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
B56F EQUB &0D
B570 EQUB &0A
#if defined _DDOS316
B571 EQUS "WD 2791 status : "
#elif defined _DDOS336
B571 EQUS "WD 2793 status : "
#else
B571 EQUS "WD 1770 status : "
#endif
B582 EQUB &FF
B583 AD 8F 10 LDA &108F
B586 20 29 A4 JSR R429 ;print hex byte
B589 4C 67 84 JMP P467 ;print newline
B58C A2 00 LDX #&00 ;&13 Read data / &17 Read data & deleted data
B58E AD A2 01 LDA &01A2 ;&0B Write data B58F=LDX #&01
B591 AD A2 02 LDA &02A2 ; B592=LDX #&02
B594 AD A2 03 LDA &03A2 ;&0F Write deleted data B595=LDX #&03
B597 AD A2 04 LDA &04A2 ;&1F Verify data B598=LDX #&04
B59A 8E 00 10 STX &1000 ;set data transfer call number
B59D 20 36 B6 JSR S636 ;set starting sector and byte count
#if defined _DDOS316
B5A0 20 5F B7 JSR S75F ;transfer data to disc
#elif defined _DDOS336
B5A0 20 5F B7 JSR S75F ;transfer data to disc
#else
B5A0 20 5D B7 JSR S75D ;transfer data to disc
#endif
B5A3 A0 0A LDY #&0A ;Y = 10 = offset of status in read/write cmd
B5A5 91 B0 STA (&B0),Y ;return status to user's OSWORD &7F block
B5A7 60 RTS
;&29 Seek
#if defined _DDOS316
B5A8 20 91 B6 JSR S691
#elif defined _DDOS336
B5A8 20 91 B6 JSR S691
#else
B5A8 20 8F B6 JSR S68F ;seek logical track
#endif
B5AB A0 08 LDY #&08
B5AD 91 B0 STA (&B0),Y
B5AF 60 RTS
;&1B Read ID
#if defined _DDOS316
B5B0 20 CD B6 JSR S6CD ;read ID and detect density
B5B3 20 CD B6 JSR S6CD ;read ID and detect density
#elif defined _DDOS336
B5B0 20 CD B6 JSR S6CD ;read ID and detect density
B5B3 20 CD B6 JSR S6CD ;read ID and detect density
#else
B5B0 20 CB B6 JSR S6CB ;read ID and detect density
B5B3 20 CB B6 JSR S6CB ;read ID and detect density
#endif
B5B6 A0 0A LDY #&0A
B5B8 91 B0 STA (&B0),Y
B5BA A8 TAY
B5BB D0 0B BNE S5C8
.S5BD
B5BD B9 90 10 LDA &1090,Y
B5C0 20 21 9E JSR QE21 ;put data byte in user memory
B5C3 C8 INY
B5C4 C0 04 CPY #&04
B5C6 D0 F5 BNE S5BD
.S5C8
B5C8 60 RTS
;&23 Format track
#if defined _DDOS316
B5C9 4C 68 B8 JMP S868
#elif defined _DDOS336
B5C9 4C 68 B8 JMP S868
#else
B5C9 4C 8B B8 JMP S88B
#endif
;&2C Read drive status
B5CC 88 DEY
#if defined _DDOS316
B5CD 20 75 B6 JSR S675 ;test write protect state
#elif defined _DDOS336
B5CD 20 75 B6 JSR S675 ;test write protect state
#else
B5CD 20 73 B6 JSR S673 ;test write protect state
#endif
B5D0 4A LSR A
B5D1 4A LSR A
B5D2 4A LSR A
B5D3 09 44 ORA #&44
B5D5 91 B0 STA (&B0),Y
.S5D7
B5D7 60 RTS
;&35 Specify
B5D8 A5 BA LDA &BA
B5DA C9 0D CMP #&0D
B5DC D0 F9 BNE S5D7
B5DE B1 B0 LDA (&B0),Y
B5E0 AA TAX
B5E1 4C 6F B6 JMP S66F
;&3A Write special registers
B5E4 B1 B0 LDA (&B0),Y
B5E6 A6 BA LDX &BA
B5E8 E0 04 CPX #&04
B5EA B0 04 BCS S5F0
B5EC 9D E0 10 STA &10E0,X
B5EF 60 RTS
.S5F0
B5F0 D0 04 BNE S5F6
B5F2 8D 01 10 STA &1001
B5F5 60 RTS
.S5F6
B5F6 E0 12 CPX #&12
B5F8 D0 16 BNE S610
#if defined _DDOS316
B5FA 4C 85 B9 JMP S985
#elif defined _DDOS336
B5FA 4C 85 B9 JMP S985
#else
B5FA 4C A8 B9 JMP S9A8
#endif
;&3D Read special registers
B5FD A6 BA LDX &BA
B5FF E0 04 CPX #&04
B601 B0 06 BCS S609
B603 BD E0 10 LDA &10E0,X
B606 91 B0 STA (&B0),Y
B608 60 RTS
.S609
B609 D0 05 BNE S610
B60B AD 01 10 LDA &1001
B60E 91 B0 STA (&B0),Y
.S610
B610 60 RTS
;Table of 8271 floppy drive controller commands with action addresses
B611 EQUB &13 ;&13 Read data
B612 EQUW &8B,&B5
B614 EQUB &0B ;&0B Write data
B615 EQUW &8E,&B5
B617 EQUB &29 ;&29 Seek
B618 EQUW &A7,&B5
B61A EQUB &1F ;&1F Verify data
B61B EQUW &97,&B5
B61D EQUB &17 ;&17 Read data & deleted data
B61E EQUW &8B,&B5
B620 EQUB &0F ;&0F Write deleted data
B621 EQUW &94,&B5
B623 EQUB &1B ;&1B Read ID
B624 EQUW &AF,&B5
B626 EQUB &23 ;&23 Format track
B627 EQUW &C8,&B5
B629 EQUB &2C ;&2C Read drive status
B62A EQUW &CB,&B5
B62C EQUB &35 ;&35 Specify
B62D EQUW &D7,&B5
B62F EQUB &3A ;&3A Write special registers
B630 EQUW &E3,&B5
B632 EQUB &3D ;&3D Read special registers
B633 EQUW &FC,&B5
B635 EQUB &00 ;terminator byte
.S636 ;Set starting sector and byte count
B636 B1 B0 LDA (&B0),Y ;get 2nd parameter = starting sector number
B638 C8 INY ;increment offset; Y = 9
B639 85 BB STA &BB ;store in zero page, &BA = track nunber
B63B B1 B0 LDA (&B0),Y ;get number of sectors + size code
B63D 20 66 A4 JSR R466 ;shift A right 5 places
B640 AA TAX ;save size code in X
B641 A9 00 LDA #&00 ;set LSB of byte count = 0
B643 85 A0 STA &A0
B645 B1 B0 LDA (&B0),Y ;get number of sectors + size code
B647 C8 INY ;increment offset; Y = 10, points to status
B648 29 1F AND #&1F ;extract number of sectors
B64A 4A LSR A ;A,&A0 = 256 x sector count; divide by two
B64B 66 A0 ROR &A0 ;= byte count if X=0, 128-byte sectors
B64D 90 03 BCC S652 ;jump into doubling loop (always)
.S64F
B64F 06 A0 ASL &A0 ;multiply byte count by two
B651 2A ROL A
.S652
B652 CA DEX ;subtract 1 from X
B653 10 FA BPL S64F ;if X was >0 then double byte count
B655 85 A1 STA &A1 ;else store high byte of byte count and exit
B657 60 RTS
.S658 ;Set control latch for drive
B658 A5 CF LDA &CF ;get current volume
B65A 29 03 AND #&03 ;extract physical drive number, clear b7..2
#if defined _DDOS356
B65C DA PHX
B65D 20 48 BF JSR SF48
B660 FA PLX
B661 8D 24 FE STA &FE24
#elif defined _DDOS357
B65C DA PHX
B65D 20 40 BF JSR SF40
B660 FA PLX
B661 8D 24 FE STA &FE24
#else
B65C 0D E3 10 ORA &10E3
B65F 29 7F AND #&7F
B661 8D 84 FE STA &FE84
#endif
B664 60 RTS
.S665
B665 20 00 A3 JSR R300 ;save AXY
B668 20 1C A8 JSR R81C ;call OSBYTE &FF = read/write startup options
B66B 8A TXA ;transfer keyboard links to A
B66C 20 5F A4 JSR R45F ;extract b5,b4 of A
.S66F
B66F 8D 8E 10 STA &108E ;save as track stepping rate
#if defined _DDOS316
B672 4C 46 B7 JMP S746
#elif defined _DDOS336
B672 4C 46 B7 JMP S746
#else
B672 60 RTS
#endif
#if defined _DDOS316
;////////////////////////////////////////////// DDOS 3.16
.S675
B675 20 3C B7 JSR S73C
B678 20 E6 B9 JSR S9E6
B67B 29 40 AND #&40
B67D 60 RTS
.S67E
B67E 20 29 A3 JSR R329 ;save XY
B681 A9 08 LDA #&08
# if defined _BUGFIX
B683 20 F6 92 JSR Q2F6
# else
B683 20 BB B6 JSR S6BB
# endif
B686 A5 CF LDA &CF ;get current volume
B688 29 01 AND #&01
B68A AA TAX
B68B A9 00 LDA #&00
B68D 9D 8C 10 STA &108C,X
B690 60 RTS
.S691
B691 A5 BA LDA &BA
B693 2C E0 10 BIT &10E0 ;test double-stepping flag
B696 50 01 BVC S699
B698 0A ASL A
.S699
B699 C9 00 CMP #&00
B69B F0 E1 BEQ S67E
B69D 20 29 A3 JSR R329 ;save XY
B6A0 48 PHA
B6A1 A5 CF LDA &CF ;get current volume
B6A3 29 01 AND #&01
B6A5 AA TAX
B6A6 BD 8C 10 LDA &108C,X
B6A9 20 8F B9 JSR S98F
B6AC 68 PLA
B6AD 9D 8C 10 STA &108C,X
B6B0 20 DA B9 JSR S9DA
B6B3 A9 18 LDA #&18
# if defined _BUGFIX
B6B5 20 F6 92 JSR Q2F6
# else
B6B5 20 BB B6 JSR S6BB
# endif
B6B8 29 10 AND #&10
B6BA 60 RTS
.S6BB
B6BB 0D 8E 10 ORA &108E ;apply track stepping rate
B6BE 20 CE B9 JSR S9CE
B6C1 4C E6 B9 JMP S9E6
.S6C4
B6C4 20 CD B6 JSR S6CD
B6C7 F0 03 BEQ S6CC
B6C9 4C B7 B9 JMP S9B7
.S6CC
B6CC 60 RTS
.S6CD
B6CD 20 29 A3 JSR R329 ;save XY
B6D0 20 3C B7 JSR S73C
B6D3 A2 04 LDX #&04
B6D5 2C E3 10 BIT &10E3
B6D8 50 0F BVC S6E9
.S6DA
B6DA AD E3 10 LDA &10E3
B6DD 09 40 ORA #&40
B6DF A0 12 LDY #&12
B6E1 20 0E B7 JSR S70E
B6E4 F0 25 BEQ S70B
B6E6 CA DEX
B6E7 F0 0F BEQ S6F8
.S6E9
B6E9 AD E3 10 LDA &10E3
B6EC 29 BF AND #&BF
B6EE A0 0A LDY #&0A
B6F0 20 0E B7 JSR S70E
B6F3 F0 16 BEQ S70B
B6F5 CA DEX
B6F6 D0 E2 BNE S6DA
.S6F8
B6F8 AD E3 10 LDA &10E3
B6FB 29 BF AND #&BF
B6FD 8D E3 10 STA &10E3
B700 20 58 B6 JSR S658 ;set control latch for drive
B703 A9 0A LDA #&0A
B705 8D E1 10 STA &10E1
B708 A9 18 LDA #&18
B70A 60 RTS
.S70B
B70B A9 00 LDA #&00
B70D 60 RTS
.S70E
B70E 8D E3 10 STA &10E3
B711 8C E1 10 STY &10E1
.S714
B714 A0 16 LDY #&16
.S716
B716 B9 5C BA LDA &BA5C,Y
B719 99 00 0D STA &0D00,Y
B71C 88 DEY
B71D 10 F7 BPL S716
B71F A9 00 LDA #&00
B721 85 A0 STA &A0
B723 20 58 B6 JSR S658 ;set control latch for drive
B726 A9 C0 LDA #&C0
B728 20 CE B9 JSR S9CE
B72B 20 E6 B9 JSR S9E6
B72E 48 PHA
B72F A0 03 LDY #&03
.S731
B731 B9 90 10 LDA &1090,Y
B734 99 02 10 STA &1002,Y
B737 88 DEY
B738 10 F7 BPL S731
B73A 68 PLA
B73B 60 RTS
.S73C
B73C A9 18 LDA #&18
B73E 20 CE B9 JSR S9CE
B741 A2 0F LDX #&0F
.S743
B743 CA DEX
B744 D0 FD BNE S743
.S746
B746 A9 D0 LDA #&D0
B748 4C CE B9 JMP S9CE
.S74B
B74B 60 RTS
.S74C
B74C 20 29 A3 JSR R329 ;save XY
B74F A9 00 LDA #&00
B751 85 BB STA &BB
B753 85 A0 STA &A0
B755 AD E1 10 LDA &10E1
B758 85 A1 STA &A1
B75A A9 04 LDA #&04
B75C 8D 00 10 STA &1000
.S75F
B75F 20 29 A3 JSR R329 ;save XY
B762 20 D6 A7 JSR R7D6
B765 20 91 B6 JSR S691
B768 A5 BA LDA &BA
B76A 20 85 B9 JSR S985
B76D 20 76 B7 JSR S776
B770 48 PHA
B771 20 7D B9 JSR S97D
B774 68 PLA
B775 60 RTS
.S776
B776 20 29 A3 JSR R329 ;save XY
B779 A5 A0 LDA &A0
B77B 48 PHA
B77C A5 A1 LDA &A1
B77E 48 PHA
B77F 20 0E B8 JSR S80E
B782 AD 01 10 LDA &1001
B785 8D 31 0D STA &0D31
B788 A5 A0 LDA &A0
B78A F0 02 BEQ S78E
B78C E6 A1 INC &A1
.S78E
B78E AD 00 10 LDA &1000
B791 29 05 AND #&05
B793 F0 14 BEQ S7A9
B795 6A ROR A
B796 B0 15 BCS S7AD
B798 A9 4C LDA #&4C
B79A 8D 08 0D STA &0D08
B79D A9 13 LDA #&13
B79F 8D 09 0D STA &0D09
B7A2 A9 0D LDA #&0D
B7A4 8D 0A 0D STA &0D0A
B7A7 D0 10 BNE S7B9
.S7A9
B7A9 A0 09 LDY #&09
B7AB D0 09 BNE S7B6
.S7AD
B7AD A9 00 LDA #&00
B7AF 85 A0 STA &A0
B7B1 20 1A B8 JSR S81A
B7B4 A0 04 LDY #&04
.S7B6
B7B6 20 E4 B7 JSR S7E4
.S7B9
B7B9 A5 F4 LDA &F4
B7BB 8D 3E 0D STA &0D3E
B7BE A5 BB LDA &BB
B7C0 20 D4 B9 JSR S9D4
B7C3 AC 00 10 LDY &1000
B7C6 B9 FF B9 LDA &B9FF,Y
B7C9 20 CE B9 JSR S9CE
B7CC A2 1E LDX #&1E
.S7CE
B7CE CA DEX
B7CF D0 FD BNE S7CE
B7D1 20 30 0D JSR &0D30
B7D4 68 PLA
B7D5 85 A1 STA &A1
B7D7 68 PLA
B7D8 85 A0 STA &A0
B7DA 20 F6 B9 JSR S9F6
B7DD AC 00 10 LDY &1000
B7E0 39 04 BA AND &BA04,Y
B7E3 60 RTS
.S7E4
B7E4 AD D5 10 LDA &10D5
B7E7 F0 1A BEQ S803
B7E9 A9 E5 LDA #&E5
B7EB 99 00 0D STA &0D00,Y
B7EE A9 FE LDA #&FE
B7F0 99 01 0D STA &0D01,Y
B7F3 A9 4C LDA #&4C
B7F5 8D 0B 0D STA &0D0B
B7F8 A9 13 LDA #&13
B7FA 8D 0C 0D STA &0D0C
B7FD A9 0D LDA #&0D
B7FF 8D 0D 0D STA &0D0D
B802 60 RTS
.S803
B803 A5 A6 LDA &A6
B805 99 00 0D STA &0D00,Y
B808 A5 A7 LDA &A7
B80A 99 01 0D STA &0D01,Y
B80D 60 RTS
.S80E
B80E A0 42 LDY #&42
.S810
B810 B9 09 BA LDA &BA09,Y
B813 99 00 0D STA &0D00,Y
B816 88 DEY
B817 10 F7 BPL S810
B819 60 RTS
.S81A
B81A A0 0F LDY #&0F
.S81C
B81C B9 4C BA LDA &BA4C,Y
B81F 99 03 0D STA &0D03,Y
B822 88 DEY
B823 10 F7 BPL S81C
B825 A9 FC LDA #&FC
B827 8D 25 0D STA &0D25
B82A 60 RTS
.S82B
B82B A9 0A LDA #&0A
B82D 2C E3 10 BIT &10E3
B830 50 02 BVC S834
B832 A9 12 LDA #&12
.S834
B834 85 A6 STA &A6
B836 0A ASL A
B837 0A ASL A
B838 85 A7 STA &A7
B83A A6 BB LDX &BB
B83C A0 00 LDY #&00
.S83E
B83E A5 BA LDA &BA
B840 99 A0 11 STA &11A0,Y
B843 C8 INY
B844 A9 00 LDA #&00
B846 99 A0 11 STA &11A0,Y
B849 C8 INY
B84A 8A TXA
B84B 99 A0 11 STA &11A0,Y
B84E C8 INY
B84F A9 01 LDA #&01
B851 99 A0 11 STA &11A0,Y
B854 C8 INY
B855 E8 INX
B856 E4 A6 CPX &A6
B858 90 02 BCC S85C
B85A A2 00 LDX #&00
.S85C
B85C C4 A7 CPY &A7
B85E 90 DE BCC S83E
B860 A9 A0 LDA #&A0
B862 85 A6 STA &A6
B864 A9 11 LDA #&11
B866 85 A7 STA &A7
.S868
B868 A9 12 LDA #&12
B86A 85 A2 STA &A2
B86C 85 A4 STA &A4
B86E A9 13 LDA #&13
B870 85 A3 STA &A3
B872 A9 15 LDA #&15
B874 85 A5 STA &A5
B876 A2 00 LDX #&00
B878 2C E3 10 BIT &10E3
B87B 50 02 BVC S87F
B87D A2 23 LDX #&23
.S87F
B87F A0 05 LDY #&05
.S881
B881 20 C2 B8 JSR S8C2
B884 88 DEY
B885 D0 FA BNE S881
B887 A0 0A LDY #&0A
B889 2C E3 10 BIT &10E3
B88C 50 02 BVC S890
B88E A0 12 LDY #&12
.S890
B890 8A TXA
B891 48 PHA
.S892
B892 20 C2 B8 JSR S8C2
B895 90 FB BCC S892
B897 68 PLA
B898 AA TAX
B899 88 DEY
B89A D0 F4 BNE S890
B89C A9 00 LDA #&00
B89E 20 15 B9 JSR S915
B8A1 20 91 B6 JSR S691
B8A4 A9 0F LDA #&0F
B8A6 2C E3 10 BIT &10E3
B8A9 50 02 BVC S8AD
B8AB A9 27 LDA #&27
.S8AD
B8AD 85 A0 STA &A0
B8AF A0 25 LDY #&25
.S8B1
B8B1 B9 73 BA LDA &BA73,Y
B8B4 99 00 0D STA &0D00,Y
B8B7 88 DEY
B8B8 10 F7 BPL S8B1
B8BA A9 F4 LDA #&F4
B8BC 20 CE B9 JSR S9CE
B8BF 4C E6 B9 JMP S9E6
.S8C2
B8C2 8A TXA
B8C3 48 PHA
B8C4 98 TYA
B8C5 48 PHA
B8C6 A0 00 LDY #&00
B8C8 38 SEC
B8C9 BD 33 B9 LDA &B933,X
B8CC 30 12 BMI S8E0
B8CE F0 09 BEQ S8D9
B8D0 85 A0 STA &A0
B8D2 BD 34 B9 LDA &B934,X
B8D5 20 15 B9 JSR S915
.S8D8
B8D8 18 CLC
.S8D9
B8D9 68 PLA
B8DA A8 TAY
B8DB 68 PLA
B8DC AA TAX
B8DD E8 INX
B8DE E8 INX
B8DF 60 RTS
.S8E0
B8E0 BD 34 B9 LDA &B934,X
B8E3 D0 1C BNE S901
B8E5 A9 01 LDA #&01
B8E7 85 A0 STA &A0
B8E9 A2 04 LDX #&04
.S8EB
B8EB A0 00 LDY #&00
B8ED 20 15 9E JSR QE15 ;get data byte from user memory
B8F0 20 15 B9 JSR S915
B8F3 E6 A6 INC &A6
B8F5 D0 02 BNE S8F9
B8F7 E6 A7 INC &A7
.S8F9
B8F9 CA DEX
B8FA D0 EF BNE S8EB
B8FC 85 A1 STA &A1
B8FE 4C D8 B8 JMP S8D8
.S901
B901 A6 A1 LDX &A1
B903 BD 79 B9 LDA &B979,X
B906 85 A0 STA &A0
B908 A2 08 LDX #&08
.S90A
B90A A9 E5 LDA #&E5
B90C 20 15 B9 JSR S915
B90F CA DEX
B910 D0 F8 BNE S90A
B912 4C D8 B8 JMP S8D8
.S915
B915 A0 00 LDY #&00
B917 91 A2 STA (&A2),Y
B919 A5 A0 LDA &A0
B91B 91 A4 STA (&A4),Y
B91D C6 A4 DEC &A4
B91F E6 A4 INC &A4
B921 D0 05 BNE S928
B923 38 SEC
B924 E9 01 SBC #&01
B926 91 A4 STA (&A4),Y
.S928
B928 E6 A2 INC &A2
B92A E6 A4 INC &A4
B92C D0 04 BNE S932
B92E E6 A3 INC &A3
B930 E6 A5 INC &A5
.S932
B932 60 RTS
;RLE tables of formatting bytes
;Single density
B933 EQUB &10,&FF
B935 EQUB &03,&00
B937 EQUB &03,&00
B939 EQUB &01,&FC
B93B EQUB &0B,&FF
B93D EQUB &03,&00
B93F EQUB &03,&00
B941 EQUB &01,&FE
B943 EQUB &FF,&00
B945 EQUB &01,&F7
B947 EQUB &0B,&FF
B949 EQUB &03,&00
B94B EQUB &03,&00
B94D EQUB &01,&FB
B94F EQUB &FF,&01
B951 EQUB &01,&F7
B953 EQUB &10,&FF
B955 EQUB &00
;Double density
B956 EQUB &28,&4E
B958 EQUB &0C,&00
B95A EQUB &03,&F6
B95C EQUB &01,&FC
B95E EQUB &19,&4E
B960 EQUB &0C,&00
B962 EQUB &03,&F5
B964 EQUB &01,&FE
B966 EQUB &FF,&00
B968 EQUB &01,&F7
B96A EQUB &16,&4E
B96C EQUB &0C,&00
B96E EQUB &03,&F5
B970 EQUB &01,&FB
B972 EQUB &FF,&01
B974 EQUB &01,&F7
B976 EQUB &16,&4E
B978 EQUB &00
B979 EQUB &10
B97A EQUB &20
B97B EQUB &40
B97C EQUB &80
.S97D
B97D A5 BA LDA &BA
B97F 2C E0 10 BIT &10E0 ;test double-stepping flag
B982 50 01 BVC S985
B984 0A ASL A
.S985
B985 48 PHA
B986 A5 CF LDA &CF ;get current volume
B988 29 01 AND #&01
B98A AA TAX
B98B 68 PLA
B98C 9D 8C 10 STA &108C,X
.S98F
B98F 49 FF EOR #&FF
B991 8D 81 FE STA &FE81
B994 60 RTS
.S995
B995 20 47 A3 JSR R347
B998 EQUB &C5
B999 EQUS " fault"
B99F EQUB &00
B9A0 20 62 A3 JSR R362
B9A3 EQUB &C5
B9A4 EQUS "Cannot recalibrate"
B9B6 EQUB &00
.S9B7
B9B7 20 62 A3 JSR R362
B9BA EQUB &C5
B9BB EQUS "Disk not formatted"
B9CD EQUB &00
.S9CE
B9CE 49 FF EOR #&FF
B9D0 8D 80 FE STA &FE80
B9D3 60 RTS
.S9D4
B9D4 49 FF EOR #&FF
B9D6 8D 82 FE STA &FE82
B9D9 60 RTS
.S9DA
B9DA 49 FF EOR #&FF
B9DC 8D 83 FE STA &FE83
B9DF 60 RTS
.S9E0
B9E0 AD 80 FE LDA &FE80
B9E3 29 80 AND #&80
B9E5 60 RTS
.S9E6
B9E6 20 29 A3 JSR R329 ;save XY
B9E9 A2 FF LDX #&FF
.S9EB
B9EB CA DEX
B9EC D0 FD BNE S9EB
.S9EE
B9EE 20 F6 B9 JSR S9F6
B9F1 30 FB BMI S9EE
B9F3 6A ROR A
B9F4 B0 F8 BCS S9EE
.S9F6
B9F6 AD 80 FE LDA &FE80
B9F9 49 FF EOR #&FF
B9FB 8D 8F 10 STA &108F
B9FE 60 RTS
B9FF EQUB &90
BA00 EQUB &B4
BA01 EQUB &90
BA02 EQUB &B5
BA03 EQUB &90
BA04 EQUB &3C
BA05 EQUB &7C
BA06 EQUB &1C
BA07 EQUB &5C
BA08 EQUB &3C
BA09 8D 2E 0D STA &0D2E
BA0C AD 83 FE LDA &FE83
BA0F 49 FF EOR #&FF
BA11 8D FF FF STA &FFFF
BA14 EE 09 0D INC &0D09
BA17 D0 03 BNE SA1C
BA19 EE 0A 0D INC &0D0A
.SA1C
BA1C C6 A0 DEC &A0
BA1E D0 16 BNE SA36
BA20 C6 A1 DEC &A1
BA22 D0 12 BNE SA36
BA24 A9 40 LDA #&40
BA26 8D 00 0D STA &0D00
BA29 A9 CE LDA #&CE
BA2B 69 01 ADC #&01
BA2D 90 00 BCC SA2F
.SA2F
BA2F A9 D0 LDA #&D0
BA31 49 FF EOR #&FF
BA33 8D 80 FE STA &FE80
.SA36
BA36 A9 00 LDA #&00
BA38 40 RTI
BA39 A9 0E LDA #&0E
BA3B 8D 30 FE STA &FE30
.SA3E
BA3E AD 80 FE LDA &FE80
BA41 10 FB BPL SA3E
BA43 6A ROR A
BA44 90 F8 BCC SA3E
BA46 A9 00 LDA #&00
BA48 8D 30 FE STA &FE30
BA4B 60 RTS
BA4C AD FF FF LDA &FFFF
BA4F 49 FF EOR #&FF
BA51 8D 83 FE STA &FE83
BA54 EE 04 0D INC &0D04
BA57 D0 03 BNE SA5C
BA59 EE 05 0D INC &0D05
.SA5C
BA5C 8D 15 0D STA &0D15
BA5F 8C 13 0D STY &0D13
BA62 A4 A0 LDY &A0
BA64 AD 83 FE LDA &FE83
BA67 49 FF EOR #&FF
BA69 99 90 10 STA &1090,Y
BA6C E6 A0 INC &A0
BA6E A0 00 LDY #&00
BA70 A9 00 LDA #&00
BA72 40 RTI
BA73 48 PHA
BA74 AD 12 13 LDA &1312
BA77 49 FF EOR #&FF
BA79 8D 83 FE STA &FE83
BA7C C6 A0 DEC &A0
BA7E D0 0A BNE SA8A
BA80 EE 02 0D INC &0D02
BA83 D0 0A BNE SA8F
BA85 EE 03 0D INC &0D03
.SA88
BA88 68 PLA
BA89 40 RTI
.SA8A
BA8A 10 FC BPL SA88
BA8C EE 21 0D INC &0D21
.SA8F
BA8F EE 20 0D INC &0D20
BA92 AD 12 15 LDA &1512
BA95 85 A0 STA &A0
BA97 68 PLA
BA98 40 RTI
;Tube host code
BA99 EA NOP
.SA9A
BA9A C9 FE CMP #&FE
BA9C 90 5C BCC SAFA
BA9E D0 1B BNE SABB
BAA0 C0 00 CPY #&00
BAA2 F0 56 BEQ SAFA
BAA4 A2 06 LDX #&06
BAA6 A9 14 LDA #&14
BAA8 20 F4 FF JSR &FFF4
.SAAB
BAAB 2C E0 FE BIT &FEE0
BAAE 10 FB BPL SAAB
BAB0 AD E1 FE LDA &FEE1
BAB3 F0 43 BEQ SAF8
BAB5 20 EE FF JSR &FFEE
BAB8 4C AB BA JMP SAAB
.SABB
BABB A9 AD LDA #&AD
BABD 8D 20 02 STA &0220
BAC0 A9 06 LDA #&06
BAC2 8D 21 02 STA &0221
BAC5 A9 16 LDA #&16
BAC7 8D 02 02 STA &0202
BACA A9 00 LDA #&00
BACC 8D 03 02 STA &0203
BACF A9 8E LDA #&8E
BAD1 8D E0 FE STA &FEE0
BAD4 A0 00 LDY #&00
.SAD6
BAD6 B9 3C BB LDA &BB3C,Y
BAD9 99 00 04 STA &0400,Y
BADC B9 3C BC LDA &BC3C,Y
BADF 99 00 05 STA &0500,Y
BAE2 B9 3C BD LDA &BD3C,Y
BAE5 99 00 06 STA &0600,Y
BAE8 88 DEY
BAE9 D0 EB BNE SAD6
BAEB 20 21 04 JSR &0421
BAEE A2 60 LDX #&60
.SAF0
BAF0 BD FB BA LDA &BAFB,X
BAF3 95 16 STA &16,X
BAF5 CA DEX
BAF6 10 F8 BPL SAF0
.SAF8
BAF8 A9 00 LDA #&00
.SAFA
BAFA 60 RTS
BAFB A9 FF LDA #&FF
BAFD 20 9E 06 JSR &069E
BB00 AD E3 FE LDA &FEE3
BB03 A9 00 LDA #&00
BB05 20 95 06 JSR &0695
BB08 A8 TAY
BB09 B1 FD LDA (&FD),Y
BB0B 20 95 06 JSR &0695
.SB0E
BB0E C8 INY
BB0F B1 FD LDA (&FD),Y
BB11 20 95 06 JSR &0695
BB14 AA TAX
BB15 D0 F7 BNE SB0E
BB17 A2 FF LDX #&FF
BB19 9A TXS
BB1A 58 CLI
.SB1B
BB1B 2C E0 FE BIT &FEE0
BB1E 10 06 BPL SB26
.SB20
BB20 AD E1 FE LDA &FEE1
BB23 20 EE FF JSR &FFEE
.SB26
BB26 2C E2 FE BIT &FEE2
BB29 10 F0 BPL SB1B
BB2B 2C E0 FE BIT &FEE0
BB2E 30 F0 BMI SB20
BB30 AE E3 FE LDX &FEE3
BB33 86 51 STX &51
BB35 6C 00 05 JMP (&0500)
BB38 EQUB &00
BB39 EQUB &80
BB3A EQUB &00
BB3B EQUB &00
BB3C 4C 84 04 JMP &0484
BB3F 4C A7 06 JMP &06A7
BB42 C9 80 CMP #&80
BB44 90 2B BCC SB71
BB46 C9 C0 CMP #&C0
BB48 B0 1A BCS SB64
BB4A 09 40 ORA #&40
BB4C C5 15 CMP &15
BB4E D0 20 BNE SB70
BB50 08 PHP
BB51 78 SEI
BB52 A9 05 LDA #&05
BB54 20 9E 06 JSR &069E
BB57 A5 15 LDA &15
BB59 20 9E 06 JSR &069E
BB5C 28 PLP
BB5D A9 80 LDA #&80
BB5F 85 15 STA &15
BB61 85 14 STA &14
BB63 60 RTS
.SB64
BB64 06 14 ASL &14
BB66 B0 06 BCS SB6E
BB68 C5 15 CMP &15
BB6A F0 04 BEQ SB70
BB6C 18 CLC
BB6D 60 RTS
.SB6E
BB6E 85 15 STA &15
.SB70
BB70 60 RTS
.SB71
BB71 08 PHP
BB72 78 SEI
BB73 84 13 STY &13
BB75 86 12 STX &12
BB77 20 9E 06 JSR &069E
BB7A AA TAX
BB7B A0 03 LDY #&03
BB7D A5 15 LDA &15
BB7F 20 9E 06 JSR &069E
.SB82
BB82 B1 12 LDA (&12),Y
BB84 20 9E 06 JSR &069E
BB87 88 DEY
BB88 10 F8 BPL SB82
BB8A A0 18 LDY #&18
BB8C 8C E0 FE STY &FEE0
BB8F BD 18 05 LDA &0518,X
BB92 8D E0 FE STA &FEE0
BB95 4A LSR A
BB96 4A LSR A
BB97 90 06 BCC SB9F
BB99 2C E5 FE BIT &FEE5
BB9C 2C E5 FE BIT &FEE5
.SB9F
BB9F 20 9E 06 JSR &069E
.SBA2
BBA2 2C E6 FE BIT &FEE6
BBA5 50 FB BVC SBA2
BBA7 B0 0D BCS SBB6
BBA9 E0 04 CPX #&04
BBAB D0 11 BNE SBBE
.SBAD
BBAD 20 14 04 JSR &0414
BBB0 20 95 06 JSR &0695
BBB3 4C 32 00 JMP &0032
.SBB6
BBB6 4A LSR A
BBB7 90 05 BCC SBBE
BBB9 A0 88 LDY #&88
BBBB 8C E0 FE STY &FEE0
.SBBE
BBBE 28 PLP
BBBF 60 RTS
BBC0 58 CLI
BBC1 B0 11 BCS SBD4
BBC3 D0 03 BNE SBC8
BBC5 4C 9C 05 JMP &059C
.SBC8
BBC8 A2 00 LDX #&00
BBCA A0 FF LDY #&FF
BBCC A9 FD LDA #&FD
BBCE 20 F4 FF JSR &FFF4
BBD1 8A TXA
BBD2 F0 D9 BEQ SBAD
.SBD4
BBD4 A9 FF LDA #&FF
BBD6 20 06 04 JSR &0406
BBD9 90 F9 BCC SBD4
BBDB 20 D2 04 JSR &04D2
.SBDE
BBDE A9 07 LDA #&07
BBE0 20 CB 04 JSR &04CB
BBE3 A0 00 LDY #&00
BBE5 84 00 STY &00
.SBE7
BBE7 B1 00 LDA (&00),Y
BBE9 8D E5 FE STA &FEE5
BBEC EA NOP
BBED EA NOP
BBEE EA NOP
BBEF C8 INY
BBF0 D0 F5 BNE SBE7
BBF2 E6 54 INC &54
BBF4 D0 06 BNE SBFC
BBF6 E6 55 INC &55
BBF8 D0 02 BNE SBFC
BBFA E6 56 INC &56
.SBFC
BBFC E6 01 INC &01
BBFE 24 01 BIT &01
BC00 50 DC BVC SBDE
BC02 20 D2 04 JSR &04D2
BC05 A9 04 LDA #&04
BC07 A0 00 LDY #&00
BC09 A2 53 LDX #&53
BC0B 4C 06 04 JMP &0406
BC0E A9 80 LDA #&80
BC10 85 54 STA &54
BC12 85 01 STA &01
BC14 A9 20 LDA #&20
BC16 2D 06 80 AND &8006
BC19 A8 TAY
BC1A 84 53 STY &53
BC1C F0 19 BEQ SC37
BC1E AE 07 80 LDX &8007
.SC21
BC21 E8 INX
BC22 BD 00 80 LDA &8000,X
BC25 D0 FA BNE SC21
BC27 BD 01 80 LDA &8001,X
BC2A 85 53 STA &53
BC2C BD 02 80 LDA &8002,X
BC2F 85 54 STA &54
BC31 BC 03 80 LDY &8003,X
BC34 BD 04 80 LDA &8004,X
.SC37
BC37 85 56 STA &56
BC39 84 55 STY &55
BC3B 60 RTS
BC3C EQUW &37,&05
BC3E EQUW &96,&05
BC40 EQUW &F2,&05
BC42 EQUW &07,&06
BC44 EQUW &27,&06
BC46 EQUW &68,&06
BC48 EQUW &5E,&05
BC4A EQUW &2D,&05
BC4C EQUW &20,&05
BC4E EQUW &42,&05
BC50 EQUW &A9,&05
BC52 EQUW &D1,&05
BC54 EQUB &86
BC55 EQUB &88
BC56 EQUB &96
BC57 EQUB &98
BC58 EQUB &18
BC59 EQUB &18
BC5A EQUB &82
BC5B EQUB &18
BC5C 20 C5 06 JSR &06C5
BC5F A8 TAY
BC60 20 C5 06 JSR &06C5
BC63 20 D4 FF JSR &FFD4
BC66 4C 9C 05 JMP &059C
BC69 20 C5 06 JSR &06C5
BC6C A8 TAY
BC6D 20 D7 FF JSR &FFD7
BC70 4C 3A 05 JMP &053A
BC73 20 E0 FF JSR &FFE0
BC76 6A ROR A
BC77 20 95 06 JSR &0695
BC7A 2A ROL A
BC7B 4C 9E 05 JMP &059E
BC7E 20 C5 06 JSR &06C5
BC81 F0 0B BEQ SC8E
BC83 48 PHA
BC84 20 82 05 JSR &0582
BC87 68 PLA
BC88 20 CE FF JSR &FFCE
BC8B 4C 9E 05 JMP &059E
.SC8E
BC8E 20 C5 06 JSR &06C5
BC91 A8 TAY
BC92 A9 00 LDA #&00
BC94 20 CE FF JSR &FFCE
BC97 4C 9C 05 JMP &059C
BC9A 20 C5 06 JSR &06C5
BC9D A8 TAY
BC9E A2 04 LDX #&04
.SCA0
BCA0 20 C5 06 JSR &06C5
BCA3 95 FF STA &FF,X
BCA5 CA DEX
BCA6 D0 F8 BNE SCA0
BCA8 20 C5 06 JSR &06C5
BCAB 20 DA FF JSR &FFDA
BCAE 20 95 06 JSR &0695
BCB1 A2 03 LDX #&03
.SCB3
BCB3 B5 00 LDA &00,X
BCB5 20 95 06 JSR &0695
BCB8 CA DEX
BCB9 10 F8 BPL SCB3
BCBB 4C 36 00 JMP &0036
BCBE A2 00 LDX #&00
BCC0 A0 00 LDY #&00
.SCC2
BCC2 20 C5 06 JSR &06C5
BCC5 99 00 07 STA &0700,Y
BCC8 C8 INY
BCC9 F0 04 BEQ SCCF
BCCB C9 0D CMP #&0D
BCCD D0 F3 BNE SCC2
.SCCF
BCCF A0 07 LDY #&07
BCD1 60 RTS
BCD2 20 82 05 JSR &0582
BCD5 20 F7 FF JSR &FFF7
BCD8 A9 7F LDA #&7F
.SCDA
BCDA 2C E2 FE BIT &FEE2
BCDD 50 FB BVC SCDA
BCDF 8D E3 FE STA &FEE3
.SCE2
BCE2 4C 36 00 JMP &0036
BCE5 A2 10 LDX #&10
.SCE7
BCE7 20 C5 06 JSR &06C5
BCEA 95 01 STA &01,X
BCEC CA DEX
BCED D0 F8 BNE SCE7
BCEF 20 82 05 JSR &0582
BCF2 86 00 STX &00
BCF4 84 01 STY &01
BCF6 A0 00 LDY #&00
BCF8 20 C5 06 JSR &06C5
BCFB 20 DD FF JSR &FFDD
BCFE 20 95 06 JSR &0695
BD01 A2 10 LDX #&10
.SD03
BD03 B5 01 LDA &01,X
BD05 20 95 06 JSR &0695
BD08 CA DEX
BD09 D0 F8 BNE SD03
BD0B F0 D5 BEQ SCE2
BD0D A2 0D LDX #&0D
.SD0F
BD0F 20 C5 06 JSR &06C5
BD12 95 FF STA &FF,X
BD14 CA DEX
BD15 D0 F8 BNE SD0F
BD17 20 C5 06 JSR &06C5
BD1A A0 00 LDY #&00
BD1C 20 D1 FF JSR &FFD1
BD1F 48 PHA
BD20 A2 0C LDX #&0C
.SD22
BD22 B5 00 LDA &00,X
BD24 20 95 06 JSR &0695
BD27 CA DEX
BD28 10 F8 BPL SD22
BD2A 68 PLA
BD2B 4C 3A 05 JMP &053A
BD2E 20 C5 06 JSR &06C5
BD31 AA TAX
BD32 20 C5 06 JSR &06C5
BD35 20 F4 FF JSR &FFF4
.SD38
BD38 2C E2 FE BIT &FEE2
BD3B 50 FB BVC SD38
BD3D 8E E3 FE STX &FEE3
.SD40
BD40 4C 36 00 JMP &0036
BD43 20 C5 06 JSR &06C5
BD46 AA TAX
BD47 20 C5 06 JSR &06C5
BD4A A8 TAY
BD4B 20 C5 06 JSR &06C5
BD4E 20 F4 FF JSR &FFF4
BD51 49 9D EOR #&9D
BD53 F0 EB BEQ SD40
BD55 6A ROR A
BD56 20 95 06 JSR &0695
.SD59
BD59 2C E2 FE BIT &FEE2
BD5C 50 FB BVC SD59
BD5E 8C E3 FE STY &FEE3
BD61 70 D5 BVS SD38
BD63 20 C5 06 JSR &06C5
BD66 A8 TAY
.SD67
BD67 2C E2 FE BIT &FEE2
BD6A 10 FB BPL SD67
BD6C AE E3 FE LDX &FEE3
BD6F CA DEX
BD70 30 0F BMI SD81
.SD72
BD72 2C E2 FE BIT &FEE2
BD75 10 FB BPL SD72
BD77 AD E3 FE LDA &FEE3
BD7A 9D 28 01 STA &0128,X
BD7D CA DEX
BD7E 10 F2 BPL SD72
BD80 98 TYA
.SD81
BD81 A2 28 LDX #&28
BD83 A0 01 LDY #&01
BD85 20 F1 FF JSR &FFF1
.SD88
BD88 2C E2 FE BIT &FEE2
BD8B 10 FB BPL SD88
BD8D AE E3 FE LDX &FEE3
BD90 CA DEX
BD91 30 0E BMI SDA1
.SD93
BD93 BC 28 01 LDY &0128,X
.SD96
BD96 2C E2 FE BIT &FEE2
BD99 50 FB BVC SD96
BD9B 8C E3 FE STY &FEE3
BD9E CA DEX
BD9F 10 F2 BPL SD93
.SDA1
BDA1 4C 36 00 JMP &0036
BDA4 A2 04 LDX #&04
.SDA6
BDA6 20 C5 06 JSR &06C5
BDA9 95 00 STA &00,X
BDAB CA DEX
BDAC 10 F8 BPL SDA6
BDAE E8 INX
BDAF A0 00 LDY #&00
BDB1 8A TXA
BDB2 20 F1 FF JSR &FFF1
BDB5 90 05 BCC SDBC
BDB7 A9 FF LDA #&FF
BDB9 4C 9E 05 JMP &059E
.SDBC
BDBC A2 00 LDX #&00
BDBE A9 7F LDA #&7F
BDC0 20 95 06 JSR &0695
.SDC3
BDC3 BD 00 07 LDA &0700,X
BDC6 20 95 06 JSR &0695
BDC9 E8 INX
BDCA C9 0D CMP #&0D
BDCC D0 F5 BNE SDC3
BDCE 4C 36 00 JMP &0036
.SDD1
BDD1 2C E2 FE BIT &FEE2
BDD4 50 FB BVC SDD1
BDD6 8D E3 FE STA &FEE3
BDD9 60 RTS
.SDDA
BDDA 2C E6 FE BIT &FEE6
BDDD 50 FB BVC SDDA
BDDF 8D E7 FE STA &FEE7
BDE2 60 RTS
BDE3 A5 FF LDA &FF
BDE5 38 SEC
BDE6 6A ROR A
BDE7 30 0F BMI SDF8
BDE9 48 PHA
BDEA A9 00 LDA #&00
BDEC 20 BC 06 JSR &06BC
BDEF 98 TYA
BDF0 20 BC 06 JSR &06BC
BDF3 8A TXA
BDF4 20 BC 06 JSR &06BC
BDF7 68 PLA
.SDF8
BDF8 2C E0 FE BIT &FEE0
BDFB 50 FB BVC SDF8
BDFD 8D E1 FE STA &FEE1
BE00 60 RTS
.SE01
BE01 2C E2 FE BIT &FEE2
BE04 10 FB BPL SE01
BE06 AD E3 FE LDA &FEE3
BE09 60 RTS
.SE0A
BE0A 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
BE0D EQUB &83 ;yellow alphanumerics
BE0E EQUB &8D ;double height
BE0F EQUS " C O P Y R I G H T N O T I C E"
BE2F EQUB &0D
BE30 EQUB &0A
BE31 EQUB &FF
BE32 60 RTS
;*COPYRIGHT
BE33 20 74 AD JSR RD74 ;set display MODE 7
BE36 20 67 84 JSR P467 ;print newline
BE39 20 0A BE JSR SE0A
BE3C 20 0A BE JSR SE0A
BE3F 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
BE42 EQUB &0D
BE43 EQUB &0A
BE44 EQUB &0A
BE45 EQUS "This Double Density Operating System"
BE69 EQUB &0D
BE6A EQUB &0A
BE6B EQUS "was developed for the BBC computer by"
BE90 EQUB &0D
BE91 EQUB &0A
BE92 EQUB &83 ;yellow alphanumerics
BE93 EQUS "SLOGGER SOFTWARE and OPUS SUPPLIES"
BEB5 EQUB &0D
BEB6 EQUB &0A
BEB7 EQUS "Any unauthorised copying of this"
BED7 EQUB &0D
BED8 EQUB &0A
BED9 EQUS "product is unlawful and may result in"
BEFE EQUB &0D
BEFF EQUB &0A
BF00 EQUS "Slogger or Opus taking appropriate"
BF22 EQUB &0D
BF23 EQUB &0A
BF24 EQUS "action."
BF2B EQUB &0D
BF2C EQUB &0A
BF2D EQUB &0A
BF2E EQUB &FF
BF2F 60 RTS
BF80 EQUB &FF,&FF,&FF,&FF
BF84 EQUB &FF,&FF,&FF,&FF
BF88 EQUB &FF,&FF,&FF,&FF
BF8C EQUB &FF,&FF,&FF,&FF
BF90 EQUB &FF,&FF,&FF,&FF
BF94 EQUB &FF,&FF,&FF,&FF
BF98 EQUB &FF,&FF,&FF,&FF
BF9C EQUB &FF,&FF,&FF,&FF
BFA0 EQUB &FF,&FF,&FF,&FF
BFA4 EQUB &FF,&FF,&FF,&FF
BFA8 EQUB &FF,&FF,&FF,&FF
BFAC EQUB &FF,&FF,&FF,&FF
BFB0 EQUB &FF,&FF,&FF,&FF
BFB4 EQUB &FF,&FF,&FF,&FF
BFB8 EQUB &FF,&FF,&FF,&FF
BFBC EQUB &FF,&FF,&FF,&FF
BFC0 EQUB &FF,&FF,&FF,&FF
BFC4 EQUB &FF,&FF,&FF,&FF
BFC8 EQUB &FF,&FF,&FF,&FF
BFCC EQUB &FF,&FF,&FF,&FF
BFD0 EQUB &FF,&FF,&FF,&FF
BFD4 EQUB &FF,&FF,&FF,&FF
BFD8 EQUB &FF,&FF,&FF,&FF
BFDC EQUB &FF,&FF,&FF,&FF
BFE0 EQUB &FF,&FF,&FF,&FF
BFE4 EQUB &FF,&FF,&FF,&FF
BFE8 EQUB &FF,&FF,&FF,&FF
BFEC EQUB &FF,&FF,&FF,&FF
BFF0 EQUB &FF,&FF,&FF,&FF
BFF4 EQUB &FF,&FF,&FF,&FF
BFF8 EQUB &FF,&FF,&FF,&FF
BFFC EQUB &FF,&FF,&FF,&FF
#elif defined _DDOS336
;////////////////////////////////////////////// DDOS 3.36
.S675
B675 20 3C B7 JSR S73C
B678 20 E0 B9 JSR S9E0
B67B 29 40 AND #&40
B67D 60 RTS
.S67E
B67E 20 29 A3 JSR R329 ;save XY
B681 A9 08 LDA #&08
# if defined _BUGFIX
B683 20 F6 92 JSR Q2F6
# else
B683 20 BB B6 JSR S6BB
# endif
B686 A5 CF LDA &CF ;get current volume
B688 29 01 AND #&01
B68A AA TAX
B68B A9 00 LDA #&00
B68D 9D 8C 10 STA &108C,X
B690 60 RTS
.S691
B691 A5 BA LDA &BA
B693 2C E0 10 BIT &10E0 ;test double-stepping flag
B696 50 01 BVC S699
B698 0A ASL A
.S699
B699 C9 00 CMP #&00
B69B F0 E1 BEQ S67E
B69D 20 29 A3 JSR R329 ;save XY
B6A0 48 PHA
B6A1 A5 CF LDA &CF ;get current volume
B6A3 29 01 AND #&01
B6A5 AA TAX
B6A6 BD 8C 10 LDA &108C,X
B6A9 20 8F B9 JSR S98F
B6AC 68 PLA
B6AD 9D 8C 10 STA &108C,X
B6B0 20 D4 B9 JSR S9D4
B6B3 A9 18 LDA #&18
# if defined _BUGFIX
B6B5 20 F6 92 JSR Q2F6
# else
B6B5 20 BB B6 JSR S6BB
# endif
B6B8 29 10 AND #&10
B6BA 60 RTS
.S6BB
B6BB 0D 8E 10 ORA &108E ;apply track stepping rate
B6BE 20 CC B9 JSR S9CC
B6C1 4C E0 B9 JMP S9E0
.S6C4
B6C4 20 CD B6 JSR S6CD
B6C7 F0 03 BEQ S6CC
B6C9 4C B5 B9 JMP S9B5
.S6CC
B6CC 60 RTS
.S6CD
B6CD 20 29 A3 JSR R329 ;save XY
B6D0 20 3C B7 JSR S73C
B6D3 A2 04 LDX #&04
B6D5 2C E3 10 BIT &10E3
B6D8 50 0F BVC S6E9
.S6DA
B6DA AD E3 10 LDA &10E3
B6DD 09 40 ORA #&40
B6DF A0 12 LDY #&12
B6E1 20 0E B7 JSR S70E
B6E4 F0 25 BEQ S70B
B6E6 CA DEX
B6E7 F0 0F BEQ S6F8
.S6E9
B6E9 AD E3 10 LDA &10E3
B6EC 29 BF AND #&BF
B6EE A0 0A LDY #&0A
B6F0 20 0E B7 JSR S70E
B6F3 F0 16 BEQ S70B
B6F5 CA DEX
B6F6 D0 E2 BNE S6DA
.S6F8
B6F8 AD E3 10 LDA &10E3
B6FB 29 BF AND #&BF
B6FD 8D E3 10 STA &10E3
B700 20 58 B6 JSR S658 ;set control latch for drive
B703 A9 0A LDA #&0A
B705 8D E1 10 STA &10E1
B708 A9 18 LDA #&18
B70A 60 RTS
.S70B
B70B A9 00 LDA #&00
B70D 60 RTS
.S70E
B70E 8D E3 10 STA &10E3
B711 8C E1 10 STY &10E1
.S714
B714 A0 14 LDY #&14
.S716
B716 B9 4E BA LDA &BA4E,Y
B719 99 00 0D STA &0D00,Y
B71C 88 DEY
B71D 10 F7 BPL S716
B71F A9 00 LDA #&00
B721 85 A0 STA &A0
B723 20 58 B6 JSR S658 ;set control latch for drive
B726 A9 C0 LDA #&C0
B728 20 CC B9 JSR S9CC
B72B 20 E0 B9 JSR S9E0
B72E 48 PHA
B72F A0 03 LDY #&03
.S731
B731 B9 90 10 LDA &1090,Y
B734 99 02 10 STA &1002,Y
B737 88 DEY
B738 10 F7 BPL S731
B73A 68 PLA
B73B 60 RTS
.S73C
B73C A9 18 LDA #&18
B73E 20 CC B9 JSR S9CC
B741 A2 0F LDX #&0F
.S743
B743 CA DEX
B744 D0 FD BNE S743
.S746
B746 A9 D0 LDA #&D0
B748 4C CC B9 JMP S9CC
.S74B
B74B 60 RTS
.S74C
B74C 20 29 A3 JSR R329 ;save XY
B74F A9 00 LDA #&00
B751 85 BB STA &BB
B753 85 A0 STA &A0
B755 AD E1 10 LDA &10E1
B758 85 A1 STA &A1
B75A A9 04 LDA #&04
B75C 8D 00 10 STA &1000
.S75F
B75F 20 29 A3 JSR R329 ;save XY
B762 20 D6 A7 JSR R7D6
B765 20 91 B6 JSR S691
B768 A5 BA LDA &BA
B76A 20 85 B9 JSR S985
B76D 20 76 B7 JSR S776
B770 48 PHA
B771 20 7D B9 JSR S97D
B774 68 PLA
B775 60 RTS
.S776
B776 20 29 A3 JSR R329 ;save XY
B779 A5 A0 LDA &A0
B77B 48 PHA
B77C A5 A1 LDA &A1
B77E 48 PHA
B77F 20 0E B8 JSR S80E
B782 AD 01 10 LDA &1001
B785 8D 2D 0D STA &0D2D
B788 A5 A0 LDA &A0
B78A F0 02 BEQ S78E
B78C E6 A1 INC &A1
.S78E
B78E AD 00 10 LDA &1000
B791 29 05 AND #&05
B793 F0 14 BEQ S7A9
B795 6A ROR A
B796 B0 15 BCS S7AD
B798 A9 4C LDA #&4C
B79A 8D 06 0D STA &0D06
B79D A9 11 LDA #&11
B79F 8D 07 0D STA &0D07
B7A2 A9 0D LDA #&0D
B7A4 8D 08 0D STA &0D08
B7A7 D0 10 BNE S7B9
.S7A9
B7A9 A0 07 LDY #&07
B7AB D0 09 BNE S7B6
.S7AD
B7AD A9 00 LDA #&00
B7AF 85 A0 STA &A0
B7B1 20 1A B8 JSR S81A
B7B4 A0 04 LDY #&04
.S7B6
B7B6 20 E4 B7 JSR S7E4
.S7B9
B7B9 A5 F4 LDA &F4
B7BB 8D 3A 0D STA &0D3A
B7BE A5 BB LDA &BB
B7C0 20 D0 B9 JSR S9D0
B7C3 AC 00 10 LDY &1000
B7C6 B9 F7 B9 LDA &B9F7,Y
B7C9 20 CC B9 JSR S9CC
B7CC A2 1E LDX #&1E
.S7CE
B7CE CA DEX
B7CF D0 FD BNE S7CE
B7D1 20 2C 0D JSR &0D2C
B7D4 68 PLA
B7D5 85 A1 STA &A1
B7D7 68 PLA
B7D8 85 A0 STA &A0
B7DA 20 F0 B9 JSR S9F0
B7DD AC 00 10 LDY &1000
B7E0 39 FC B9 AND &B9FC,Y
B7E3 60 RTS
.S7E4
B7E4 AD D5 10 LDA &10D5
B7E7 F0 1A BEQ S803
B7E9 A9 E5 LDA #&E5
B7EB 99 00 0D STA &0D00,Y
B7EE A9 FE LDA #&FE
B7F0 99 01 0D STA &0D01,Y
B7F3 A9 4C LDA #&4C
B7F5 8D 09 0D STA &0D09
B7F8 A9 11 LDA #&11
B7FA 8D 0A 0D STA &0D0A
B7FD A9 0D LDA #&0D
B7FF 8D 0B 0D STA &0D0B
B802 60 RTS
.S803
B803 A5 A6 LDA &A6
B805 99 00 0D STA &0D00,Y
B808 A5 A7 LDA &A7
B80A 99 01 0D STA &0D01,Y
B80D 60 RTS
.S80E
B80E A0 3E LDY #&3E
.S810
B810 B9 01 BA LDA &BA01,Y
B813 99 00 0D STA &0D00,Y
B816 88 DEY
B817 10 F7 BPL S810
B819 60 RTS
.S81A
B81A A0 0D LDY #&0D
.S81C
B81C B9 40 BA LDA &BA40,Y
B81F 99 03 0D STA &0D03,Y
B822 88 DEY
B823 10 F7 BPL S81C
B825 A9 FC LDA #&FC
B827 8D 23 0D STA &0D23
B82A 60 RTS
.S82B
B82B A9 0A LDA #&0A
B82D 2C E3 10 BIT &10E3
B830 50 02 BVC S834
B832 A9 12 LDA #&12
.S834
B834 85 A6 STA &A6
B836 0A ASL A
B837 0A ASL A
B838 85 A7 STA &A7
B83A A6 BB LDX &BB
B83C A0 00 LDY #&00
.S83E
B83E A5 BA LDA &BA
B840 99 A0 11 STA &11A0,Y
B843 C8 INY
B844 A9 00 LDA #&00
B846 99 A0 11 STA &11A0,Y
B849 C8 INY
B84A 8A TXA
B84B 99 A0 11 STA &11A0,Y
B84E C8 INY
B84F A9 01 LDA #&01
B851 99 A0 11 STA &11A0,Y
B854 C8 INY
B855 E8 INX
B856 E4 A6 CPX &A6
B858 90 02 BCC S85C
B85A A2 00 LDX #&00
.S85C
B85C C4 A7 CPY &A7
B85E 90 DE BCC S83E
B860 A9 A0 LDA #&A0
B862 85 A6 STA &A6
B864 A9 11 LDA #&11
B866 85 A7 STA &A7
.S868
B868 A9 12 LDA #&12
B86A 85 A2 STA &A2
B86C 85 A4 STA &A4
B86E A9 13 LDA #&13
B870 85 A3 STA &A3
B872 A9 15 LDA #&15
B874 85 A5 STA &A5
B876 A2 00 LDX #&00
B878 2C E3 10 BIT &10E3
B87B 50 02 BVC S87F
B87D A2 23 LDX #&23
.S87F
B87F A0 05 LDY #&05
.S881
B881 20 C2 B8 JSR S8C2
B884 88 DEY
B885 D0 FA BNE S881
B887 A0 0A LDY #&0A
B889 2C E3 10 BIT &10E3
B88C 50 02 BVC S890
B88E A0 12 LDY #&12
.S890
B890 8A TXA
B891 48 PHA
.S892
B892 20 C2 B8 JSR S8C2
B895 90 FB BCC S892
B897 68 PLA
B898 AA TAX
B899 88 DEY
B89A D0 F4 BNE S890
B89C A9 00 LDA #&00
B89E 20 15 B9 JSR S915
B8A1 20 91 B6 JSR S691
B8A4 A9 0F LDA #&0F
B8A6 2C E3 10 BIT &10E3
B8A9 50 02 BVC S8AD
B8AB A9 27 LDA #&27
.S8AD
B8AD 85 A0 STA &A0
B8AF A0 23 LDY #&23
.S8B1
B8B1 B9 63 BA LDA &BA63,Y
B8B4 99 00 0D STA &0D00,Y
B8B7 88 DEY
B8B8 10 F7 BPL S8B1
B8BA A9 F4 LDA #&F4
B8BC 20 CC B9 JSR S9CC
B8BF 4C E0 B9 JMP S9E0
.S8C2
B8C2 8A TXA
B8C3 48 PHA
B8C4 98 TYA
B8C5 48 PHA
B8C6 A0 00 LDY #&00
B8C8 38 SEC
B8C9 BD 33 B9 LDA &B933,X
B8CC 30 12 BMI S8E0
B8CE F0 09 BEQ S8D9
B8D0 85 A0 STA &A0
B8D2 BD 34 B9 LDA &B934,X
B8D5 20 15 B9 JSR S915
.S8D8
B8D8 18 CLC
.S8D9
B8D9 68 PLA
B8DA A8 TAY
B8DB 68 PLA
B8DC AA TAX
B8DD E8 INX
B8DE E8 INX
B8DF 60 RTS
.S8E0
B8E0 BD 34 B9 LDA &B934,X
B8E3 D0 1C BNE S901
B8E5 A9 01 LDA #&01
B8E7 85 A0 STA &A0
B8E9 A2 04 LDX #&04
.S8EB
B8EB A0 00 LDY #&00
B8ED 20 15 9E JSR QE15 ;get data byte from user memory
B8F0 20 15 B9 JSR S915
B8F3 E6 A6 INC &A6
B8F5 D0 02 BNE S8F9
B8F7 E6 A7 INC &A7
.S8F9
B8F9 CA DEX
B8FA D0 EF BNE S8EB
B8FC 85 A1 STA &A1
B8FE 4C D8 B8 JMP S8D8
.S901
B901 A6 A1 LDX &A1
B903 BD 79 B9 LDA &B979,X
B906 85 A0 STA &A0
B908 A2 08 LDX #&08
.S90A
B90A A9 E5 LDA #&E5
B90C 20 15 B9 JSR S915
B90F CA DEX
B910 D0 F8 BNE S90A
B912 4C D8 B8 JMP S8D8
.S915
B915 A0 00 LDY #&00
B917 91 A2 STA (&A2),Y
B919 A5 A0 LDA &A0
B91B 91 A4 STA (&A4),Y
B91D C6 A4 DEC &A4
B91F E6 A4 INC &A4
B921 D0 05 BNE S928
B923 38 SEC
B924 E9 01 SBC #&01
B926 91 A4 STA (&A4),Y
.S928
B928 E6 A2 INC &A2
B92A E6 A4 INC &A4
B92C D0 04 BNE S932
B92E E6 A3 INC &A3
B930 E6 A5 INC &A5
.S932
B932 60 RTS
B933 EQUB &10,&FF
B935 EQUB &03,&00
B937 EQUB &03,&00
B939 EQUB &01,&FC
B93B EQUB &0B,&FF
B93D EQUB &03,&00
B93F EQUB &03,&00
B941 EQUB &01,&FE
B943 EQUB &FF,&00
B945 EQUB &01,&F7
B947 EQUB &0B,&FF
B949 EQUB &03,&00
B94B EQUB &03,&00
B94D EQUB &01,&FB
B94F EQUB &FF,&01
B951 EQUB &01,&F7
B953 EQUB &10,&FF
B955 EQUB &00
B956 EQUB &28,&4E
B958 EQUB &0C,&00
B95A EQUB &03,&F6
B95C EQUB &01,&FC
B95E EQUB &19,&4E
B960 EQUB &0C,&00
B962 EQUB &03,&F5
B964 EQUB &01,&FE
B966 EQUB &FF,&00
B968 EQUB &01,&F7
B96A EQUB &16,&4E
B96C EQUB &0C,&00
B96E EQUB &03,&F5
B970 EQUB &01,&FB
B972 EQUB &FF,&01
B974 EQUB &01,&F7
B976 EQUB &16,&4E
B978 EQUB &00
B979 EQUB &10
B97A EQUB &20
B97B EQUB &40
B97C EQUB &80
.S97D
B97D A5 BA LDA &BA
B97F 2C E0 10 BIT &10E0 ;test double-stepping flag
B982 50 01 BVC S985
B984 0A ASL A
.S985
B985 48 PHA
B986 A5 CF LDA &CF ;get current volume
B988 29 01 AND #&01
B98A AA TAX
B98B 68 PLA
B98C 9D 8C 10 STA &108C,X
.S98F
B98F 8D 81 FE STA &FE81
B992 60 RTS
.S993
B993 20 47 A3 JSR R347
B996 EQUB &C5
B997 EQUS " fault"
B99D EQUB &00
B99E 20 62 A3 JSR R362
B9A1 EQUB &C5
B9A2 EQUS "Cannot recalibrate"
B9B4 EQUB &00
.S9B5
B9B5 20 62 A3 JSR R362
B9B8 EQUB &C5
B9B9 EQUS "Disk not formatted"
B9CB EQUB &00
.S9CC
B9CC 8D 80 FE STA &FE80
B9CF 60 RTS
.S9D0
B9D0 8D 82 FE STA &FE82
B9D3 60 RTS
.S9D4
B9D4 8D 83 FE STA &FE83
B9D7 60 RTS
.S9D8
B9D8 AD 80 FE LDA &FE80
B9DB 29 80 AND #&80
B9DD 49 80 EOR #&80
B9DF 60 RTS
.S9E0
B9E0 20 29 A3 JSR R329 ;save XY
B9E3 A2 FF LDX #&FF
.S9E5
B9E5 CA DEX
B9E6 D0 FD BNE S9E5
.S9E8
B9E8 20 F0 B9 JSR S9F0
B9EB 30 FB BMI S9E8
B9ED 6A ROR A
B9EE B0 F8 BCS S9E8
.S9F0
B9F0 AD 80 FE LDA &FE80
B9F3 8D 8F 10 STA &108F
B9F6 60 RTS
B9F7 EQUB &90
B9F8 EQUB &B4
B9F9 EQUB &90
B9FA EQUB &B5
B9FB EQUB &90
B9FC EQUB &3C
B9FD EQUB &7C
B9FE EQUB &1C
B9FF EQUB &5C
BA00 EQUB &3C
BA01 8D 2A 0D STA &0D2A
BA04 AD 83 FE LDA &FE83
BA07 8D FF FF STA &FFFF
BA0A EE 07 0D INC &0D07
BA0D D0 03 BNE SA12
BA0F EE 08 0D INC &0D08
.SA12
BA12 C6 A0 DEC &A0
BA14 D0 14 BNE SA2A
BA16 C6 A1 DEC &A1
BA18 D0 10 BNE SA2A
BA1A A9 40 LDA #&40
BA1C 8D 00 0D STA &0D00
BA1F A9 CE LDA #&CE
BA21 69 01 ADC #&01
BA23 90 00 BCC SA25
.SA25
BA25 A9 D0 LDA #&D0
BA27 8D 80 FE STA &FE80
.SA2A
BA2A A9 00 LDA #&00
BA2C 40 RTI
BA2D A9 0E LDA #&0E
BA2F 8D 30 FE STA &FE30
.SA32
BA32 AD 80 FE LDA &FE80
BA35 30 FB BMI SA32
BA37 6A ROR A
BA38 B0 F8 BCS SA32
BA3A A9 00 LDA #&00
BA3C 8D 30 FE STA &FE30
BA3F 60 RTS
BA40 AD FF FF LDA &FFFF
BA43 8D 83 FE STA &FE83
BA46 EE 04 0D INC &0D04
BA49 D0 03 BNE SA4E
BA4B EE 05 0D INC &0D05
.SA4E
BA4E 8D 13 0D STA &0D13
BA51 8C 11 0D STY &0D11
BA54 A4 A0 LDY &A0
BA56 AD 83 FE LDA &FE83
BA59 99 90 10 STA &1090,Y
BA5C E6 A0 INC &A0
BA5E A0 00 LDY #&00
BA60 A9 00 LDA #&00
BA62 40 RTI
BA63 48 PHA
BA64 AD 12 13 LDA &1312
BA67 8D 83 FE STA &FE83
BA6A C6 A0 DEC &A0
BA6C D0 0A BNE SA78
BA6E EE 02 0D INC &0D02
BA71 D0 0A BNE SA7D
BA73 EE 03 0D INC &0D03
.SA76
BA76 68 PLA
BA77 40 RTI
.SA78
BA78 10 FC BPL SA76
BA7A EE 1F 0D INC &0D1F
.SA7D
BA7D EE 1E 0D INC &0D1E
BA80 AD 12 15 LDA &1512
BA83 85 A0 STA &A0
BA85 68 PLA
BA86 40 RTI
BA87 EA NOP
.SA88
BA88 C9 FE CMP #&FE
BA8A 90 5C BCC SAE8
BA8C D0 1B BNE SAA9
BA8E C0 00 CPY #&00
BA90 F0 56 BEQ SAE8
BA92 A2 06 LDX #&06
BA94 A9 14 LDA #&14
BA96 20 F4 FF JSR &FFF4
.SA99
BA99 2C E0 FE BIT &FEE0
BA9C 10 FB BPL SA99
BA9E AD E1 FE LDA &FEE1
BAA1 F0 43 BEQ SAE6
BAA3 20 EE FF JSR &FFEE
BAA6 4C 99 BA JMP SA99
.SAA9
BAA9 A9 AD LDA #&AD
BAAB 8D 20 02 STA &0220
BAAE A9 06 LDA #&06
BAB0 8D 21 02 STA &0221
BAB3 A9 16 LDA #&16
BAB5 8D 02 02 STA &0202
BAB8 A9 00 LDA #&00
BABA 8D 03 02 STA &0203
BABD A9 8E LDA #&8E
BABF 8D E0 FE STA &FEE0
BAC2 A0 00 LDY #&00
.SAC4
BAC4 B9 2A BB LDA &BB2A,Y
BAC7 99 00 04 STA &0400,Y
BACA B9 2A BC LDA &BC2A,Y
BACD 99 00 05 STA &0500,Y
BAD0 B9 2A BD LDA &BD2A,Y
BAD3 99 00 06 STA &0600,Y
BAD6 88 DEY
BAD7 D0 EB BNE SAC4
BAD9 20 21 04 JSR &0421
BADC A2 60 LDX #&60
.SADE
BADE BD E9 BA LDA &BAE9,X
BAE1 95 16 STA &16,X
BAE3 CA DEX
BAE4 10 F8 BPL SADE
.SAE6
BAE6 A9 00 LDA #&00
.SAE8
BAE8 60 RTS
BAE9 A9 FF LDA #&FF
BAEB 20 9E 06 JSR &069E
BAEE AD E3 FE LDA &FEE3
BAF1 A9 00 LDA #&00
BAF3 20 95 06 JSR &0695
BAF6 A8 TAY
BAF7 B1 FD LDA (&FD),Y
BAF9 20 95 06 JSR &0695
.SAFC
BAFC C8 INY
BAFD B1 FD LDA (&FD),Y
BAFF 20 95 06 JSR &0695
BB02 AA TAX
BB03 D0 F7 BNE SAFC
BB05 A2 FF LDX #&FF
BB07 9A TXS
BB08 58 CLI
.SB09
BB09 2C E0 FE BIT &FEE0
BB0C 10 06 BPL SB14
.SB0E
BB0E AD E1 FE LDA &FEE1
BB11 20 EE FF JSR &FFEE
.SB14
BB14 2C E2 FE BIT &FEE2
BB17 10 F0 BPL SB09
BB19 2C E0 FE BIT &FEE0
BB1C 30 F0 BMI SB0E
BB1E AE E3 FE LDX &FEE3
BB21 86 51 STX &51
BB23 6C 00 05 JMP (&0500)
BB26 EQUB &00
BB27 EQUB &80
BB28 EQUB &00
BB29 EQUB &00
BB2A 4C 84 04 JMP &0484
BB2D 4C A7 06 JMP &06A7
BB30 C9 80 CMP #&80
BB32 90 2B BCC SB5F
BB34 C9 C0 CMP #&C0
BB36 B0 1A BCS SB52
BB38 09 40 ORA #&40
BB3A C5 15 CMP &15
BB3C D0 20 BNE SB5E
BB3E 08 PHP
BB3F 78 SEI
BB40 A9 05 LDA #&05
BB42 20 9E 06 JSR &069E
BB45 A5 15 LDA &15
BB47 20 9E 06 JSR &069E
BB4A 28 PLP
BB4B A9 80 LDA #&80
BB4D 85 15 STA &15
BB4F 85 14 STA &14
BB51 60 RTS
.SB52
BB52 06 14 ASL &14
BB54 B0 06 BCS SB5C
BB56 C5 15 CMP &15
BB58 F0 04 BEQ SB5E
BB5A 18 CLC
BB5B 60 RTS
.SB5C
BB5C 85 15 STA &15
.SB5E
BB5E 60 RTS
.SB5F
BB5F 08 PHP
BB60 78 SEI
BB61 84 13 STY &13
BB63 86 12 STX &12
BB65 20 9E 06 JSR &069E
BB68 AA TAX
BB69 A0 03 LDY #&03
BB6B A5 15 LDA &15
BB6D 20 9E 06 JSR &069E
.SB70
BB70 B1 12 LDA (&12),Y
BB72 20 9E 06 JSR &069E
BB75 88 DEY
BB76 10 F8 BPL SB70
BB78 A0 18 LDY #&18
BB7A 8C E0 FE STY &FEE0
BB7D BD 18 05 LDA &0518,X
BB80 8D E0 FE STA &FEE0
BB83 4A LSR A
BB84 4A LSR A
BB85 90 06 BCC SB8D
BB87 2C E5 FE BIT &FEE5
BB8A 2C E5 FE BIT &FEE5
.SB8D
BB8D 20 9E 06 JSR &069E
.SB90
BB90 2C E6 FE BIT &FEE6
BB93 50 FB BVC SB90
BB95 B0 0D BCS SBA4
BB97 E0 04 CPX #&04
BB99 D0 11 BNE SBAC
.SB9B
BB9B 20 14 04 JSR &0414
BB9E 20 95 06 JSR &0695
BBA1 4C 32 00 JMP &0032
.SBA4
BBA4 4A LSR A
BBA5 90 05 BCC SBAC
BBA7 A0 88 LDY #&88
BBA9 8C E0 FE STY &FEE0
.SBAC
BBAC 28 PLP
BBAD 60 RTS
BBAE 58 CLI
BBAF B0 11 BCS SBC2
BBB1 D0 03 BNE SBB6
BBB3 4C 9C 05 JMP &059C
.SBB6
BBB6 A2 00 LDX #&00
BBB8 A0 FF LDY #&FF
BBBA A9 FD LDA #&FD
BBBC 20 F4 FF JSR &FFF4
BBBF 8A TXA
BBC0 F0 D9 BEQ SB9B
.SBC2
BBC2 A9 FF LDA #&FF
BBC4 20 06 04 JSR &0406
BBC7 90 F9 BCC SBC2
BBC9 20 D2 04 JSR &04D2
.SBCC
BBCC A9 07 LDA #&07
BBCE 20 CB 04 JSR &04CB
BBD1 A0 00 LDY #&00
BBD3 84 00 STY &00
.SBD5
BBD5 B1 00 LDA (&00),Y
BBD7 8D E5 FE STA &FEE5
BBDA EA NOP
BBDB EA NOP
BBDC EA NOP
BBDD C8 INY
BBDE D0 F5 BNE SBD5
BBE0 E6 54 INC &54
BBE2 D0 06 BNE SBEA
BBE4 E6 55 INC &55
BBE6 D0 02 BNE SBEA
BBE8 E6 56 INC &56
.SBEA
BBEA E6 01 INC &01
BBEC 24 01 BIT &01
BBEE 50 DC BVC SBCC
BBF0 20 D2 04 JSR &04D2
BBF3 A9 04 LDA #&04
BBF5 A0 00 LDY #&00
BBF7 A2 53 LDX #&53
BBF9 4C 06 04 JMP &0406
BBFC A9 80 LDA #&80
BBFE 85 54 STA &54
BC00 85 01 STA &01
BC02 A9 20 LDA #&20
BC04 2D 06 80 AND &8006
BC07 A8 TAY
BC08 84 53 STY &53
BC0A F0 19 BEQ SC25
BC0C AE 07 80 LDX &8007
.SC0F
BC0F E8 INX
BC10 BD 00 80 LDA &8000,X
BC13 D0 FA BNE SC0F
BC15 BD 01 80 LDA &8001,X
BC18 85 53 STA &53
BC1A BD 02 80 LDA &8002,X
BC1D 85 54 STA &54
BC1F BC 03 80 LDY &8003,X
BC22 BD 04 80 LDA &8004,X
.SC25
BC25 85 56 STA &56
BC27 84 55 STY &55
BC29 60 RTS
BC2A EQUW &37,&05
BC2C EQUW &96,&05
BC2E EQUW &F2,&05
BC30 EQUW &07,&06
BC32 EQUW &27,&06
BC34 EQUW &68,&06
BC36 EQUW &5E,&05
BC38 EQUW &2D,&05
BC3A EQUW &20,&05
BC3C EQUW &42,&05
BC3E EQUW &A9,&05
BC40 EQUW &D1,&05
BC42 EQUB &86
BC43 EQUB &88
BC44 EQUB &96
BC45 EQUB &98
BC46 EQUB &18
BC47 EQUB &18
BC48 EQUB &82
BC49 EQUB &18
BC4A 20 C5 06 JSR &06C5
BC4D A8 TAY
BC4E 20 C5 06 JSR &06C5
BC51 20 D4 FF JSR &FFD4
BC54 4C 9C 05 JMP &059C
BC57 20 C5 06 JSR &06C5
BC5A A8 TAY
BC5B 20 D7 FF JSR &FFD7
BC5E 4C 3A 05 JMP &053A
BC61 20 E0 FF JSR &FFE0
BC64 6A ROR A
BC65 20 95 06 JSR &0695
BC68 2A ROL A
BC69 4C 9E 05 JMP &059E
BC6C 20 C5 06 JSR &06C5
BC6F F0 0B BEQ SC7C
BC71 48 PHA
BC72 20 82 05 JSR &0582
BC75 68 PLA
BC76 20 CE FF JSR &FFCE
BC79 4C 9E 05 JMP &059E
.SC7C
BC7C 20 C5 06 JSR &06C5
BC7F A8 TAY
BC80 A9 00 LDA #&00
BC82 20 CE FF JSR &FFCE
BC85 4C 9C 05 JMP &059C
BC88 20 C5 06 JSR &06C5
BC8B A8 TAY
BC8C A2 04 LDX #&04
.SC8E
BC8E 20 C5 06 JSR &06C5
BC91 95 FF STA &FF,X
BC93 CA DEX
BC94 D0 F8 BNE SC8E
BC96 20 C5 06 JSR &06C5
BC99 20 DA FF JSR &FFDA
BC9C 20 95 06 JSR &0695
BC9F A2 03 LDX #&03
.SCA1
BCA1 B5 00 LDA &00,X
BCA3 20 95 06 JSR &0695
BCA6 CA DEX
BCA7 10 F8 BPL SCA1
BCA9 4C 36 00 JMP &0036
BCAC A2 00 LDX #&00
BCAE A0 00 LDY #&00
.SCB0
BCB0 20 C5 06 JSR &06C5
BCB3 99 00 07 STA &0700,Y
BCB6 C8 INY
BCB7 F0 04 BEQ SCBD
BCB9 C9 0D CMP #&0D
BCBB D0 F3 BNE SCB0
.SCBD
BCBD A0 07 LDY #&07
BCBF 60 RTS
BCC0 20 82 05 JSR &0582
BCC3 20 F7 FF JSR &FFF7
BCC6 A9 7F LDA #&7F
.SCC8
BCC8 2C E2 FE BIT &FEE2
BCCB 50 FB BVC SCC8
BCCD 8D E3 FE STA &FEE3
.SCD0
BCD0 4C 36 00 JMP &0036
BCD3 A2 10 LDX #&10
.SCD5
BCD5 20 C5 06 JSR &06C5
BCD8 95 01 STA &01,X
BCDA CA DEX
BCDB D0 F8 BNE SCD5
BCDD 20 82 05 JSR &0582
BCE0 86 00 STX &00
BCE2 84 01 STY &01
BCE4 A0 00 LDY #&00
BCE6 20 C5 06 JSR &06C5
BCE9 20 DD FF JSR &FFDD
BCEC 20 95 06 JSR &0695
BCEF A2 10 LDX #&10
.SCF1
BCF1 B5 01 LDA &01,X
BCF3 20 95 06 JSR &0695
BCF6 CA DEX
BCF7 D0 F8 BNE SCF1
BCF9 F0 D5 BEQ SCD0
BCFB A2 0D LDX #&0D
.SCFD
BCFD 20 C5 06 JSR &06C5
BD00 95 FF STA &FF,X
BD02 CA DEX
BD03 D0 F8 BNE SCFD
BD05 20 C5 06 JSR &06C5
BD08 A0 00 LDY #&00
BD0A 20 D1 FF JSR &FFD1
BD0D 48 PHA
BD0E A2 0C LDX #&0C
.SD10
BD10 B5 00 LDA &00,X
BD12 20 95 06 JSR &0695
BD15 CA DEX
BD16 10 F8 BPL SD10
BD18 68 PLA
BD19 4C 3A 05 JMP &053A
BD1C 20 C5 06 JSR &06C5
BD1F AA TAX
BD20 20 C5 06 JSR &06C5
BD23 20 F4 FF JSR &FFF4
.SD26
BD26 2C E2 FE BIT &FEE2
BD29 50 FB BVC SD26
BD2B 8E E3 FE STX &FEE3
.SD2E
BD2E 4C 36 00 JMP &0036
BD31 20 C5 06 JSR &06C5
BD34 AA TAX
BD35 20 C5 06 JSR &06C5
BD38 A8 TAY
BD39 20 C5 06 JSR &06C5
BD3C 20 F4 FF JSR &FFF4
BD3F 49 9D EOR #&9D
BD41 F0 EB BEQ SD2E
BD43 6A ROR A
BD44 20 95 06 JSR &0695
.SD47
BD47 2C E2 FE BIT &FEE2
BD4A 50 FB BVC SD47
BD4C 8C E3 FE STY &FEE3
BD4F 70 D5 BVS SD26
BD51 20 C5 06 JSR &06C5
BD54 A8 TAY
.SD55
BD55 2C E2 FE BIT &FEE2
BD58 10 FB BPL SD55
BD5A AE E3 FE LDX &FEE3
BD5D CA DEX
BD5E 30 0F BMI SD6F
.SD60
BD60 2C E2 FE BIT &FEE2
BD63 10 FB BPL SD60
BD65 AD E3 FE LDA &FEE3
BD68 9D 28 01 STA &0128,X
BD6B CA DEX
BD6C 10 F2 BPL SD60
BD6E 98 TYA
.SD6F
BD6F A2 28 LDX #&28
BD71 A0 01 LDY #&01
BD73 20 F1 FF JSR &FFF1
.SD76
BD76 2C E2 FE BIT &FEE2
BD79 10 FB BPL SD76
BD7B AE E3 FE LDX &FEE3
BD7E CA DEX
BD7F 30 0E BMI SD8F
.SD81
BD81 BC 28 01 LDY &0128,X
.SD84
BD84 2C E2 FE BIT &FEE2
BD87 50 FB BVC SD84
BD89 8C E3 FE STY &FEE3
BD8C CA DEX
BD8D 10 F2 BPL SD81
.SD8F
BD8F 4C 36 00 JMP &0036
BD92 A2 04 LDX #&04
.SD94
BD94 20 C5 06 JSR &06C5
BD97 95 00 STA &00,X
BD99 CA DEX
BD9A 10 F8 BPL SD94
BD9C E8 INX
BD9D A0 00 LDY #&00
BD9F 8A TXA
BDA0 20 F1 FF JSR &FFF1
BDA3 90 05 BCC SDAA
BDA5 A9 FF LDA #&FF
BDA7 4C 9E 05 JMP &059E
.SDAA
BDAA A2 00 LDX #&00
BDAC A9 7F LDA #&7F
BDAE 20 95 06 JSR &0695
.SDB1
BDB1 BD 00 07 LDA &0700,X
BDB4 20 95 06 JSR &0695
BDB7 E8 INX
BDB8 C9 0D CMP #&0D
BDBA D0 F5 BNE SDB1
BDBC 4C 36 00 JMP &0036
.SDBF
BDBF 2C E2 FE BIT &FEE2
BDC2 50 FB BVC SDBF
BDC4 8D E3 FE STA &FEE3
BDC7 60 RTS
.SDC8
BDC8 2C E6 FE BIT &FEE6
BDCB 50 FB BVC SDC8
BDCD 8D E7 FE STA &FEE7
BDD0 60 RTS
BDD1 A5 FF LDA &FF
BDD3 38 SEC
BDD4 6A ROR A
BDD5 30 0F BMI SDE6
BDD7 48 PHA
BDD8 A9 00 LDA #&00
BDDA 20 BC 06 JSR &06BC
BDDD 98 TYA
BDDE 20 BC 06 JSR &06BC
BDE1 8A TXA
BDE2 20 BC 06 JSR &06BC
BDE5 68 PLA
.SDE6
BDE6 2C E0 FE BIT &FEE0
BDE9 50 FB BVC SDE6
BDEB 8D E1 FE STA &FEE1
BDEE 60 RTS
.SDEF
BDEF 2C E2 FE BIT &FEE2
BDF2 10 FB BPL SDEF
BDF4 AD E3 FE LDA &FEE3
BDF7 60 RTS
.SDF8
BDF8 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
BDFB EQUB &83 ;yellow alphanumerics
BDFC EQUB &8D ;double height
BDFD EQUS " C O P Y R I G H T N O T I C E"
BE1D EQUB &0D
BE1E EQUB &0A
BE1F EQUB &FF
BE20 60 RTS
;*COPYRIGHT
BE21 20 74 AD JSR RD74 ;set display MODE 7
BE24 20 67 84 JSR P467 ;print newline
BE27 20 F8 BD JSR SDF8
BE2A 20 F8 BD JSR SDF8
BE2D 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
BE30 EQUB &0D
BE31 EQUB &0A
BE32 EQUB &0A
BE33 EQUS "This Double Density Operating System"
BE57 EQUB &0D
BE58 EQUB &0A
BE59 EQUS "was developed for the BBC computer by"
BE7E EQUB &0D
BE7F EQUB &0A
BE80 EQUB &83 ;yellow alphanumerics
BE81 EQUS "SLOGGER SOFTWARE and OPUS SUPPLIES"
BEA3 EQUB &0D
BEA4 EQUB &0A
BEA5 EQUS "Any unauthorised copying of this"
BEC5 EQUB &0D
BEC6 EQUB &0A
BEC7 EQUS "product is unlawful and may result in"
BEEC EQUB &0D
BEED EQUB &0A
BEEE EQUS "Slogger or Opus taking appropriate"
BF10 EQUB &0D
BF11 EQUB &0A
BF12 EQUS "action."
BF19 EQUB &0D
BF1A EQUB &0A
BF1B EQUB &0A
BF1C EQUB &FF
BF1D 60 RTS
BF80 EQUB &FF,&FF,&FF,&FF
BF84 EQUB &FF,&FF,&FF,&FF
BF88 EQUB &FF,&FF,&FF,&FF
BF8C EQUB &FF,&FF,&FF,&FF
BF90 EQUB &FF,&FF,&FF,&FF
BF94 EQUB &FF,&FF,&FF,&FF
BF98 EQUB &FF,&FF,&FF,&FF
BF9C EQUB &FF,&FF,&FF,&FF
BFA0 EQUB &FF,&FF,&FF,&FF
BFA4 EQUB &FF,&FF,&FF,&FF
BFA8 EQUB &FF,&FF,&FF,&FF
BFAC EQUB &FF,&FF,&FF,&FF
BFB0 EQUB &FF,&FF,&FF,&FF
BFB4 EQUB &FF,&FF,&FF,&FF
BFB8 EQUB &FF,&FF,&FF,&FF
BFBC EQUB &FF,&FF,&FF,&FF
BFC0 EQUB &FF,&FF,&FF,&FF
BFC4 EQUB &FF,&FF,&FF,&FF
BFC8 EQUB &FF,&FF,&FF,&FF
BFCC EQUB &FF,&FF,&FF,&FF
BFD0 EQUB &FF,&FF,&FF,&FF
BFD4 EQUB &FF,&FF,&FF,&FF
BFD8 EQUB &FF,&FF,&FF,&FF
BFDC EQUB &FF,&FF,&FF,&FF
BFE0 EQUB &FF,&FF,&FF,&FF
BFE4 EQUB &FF,&FF,&FF,&FF
BFE8 EQUB &FF,&FF,&FF,&FF
BFEC EQUB &FF,&FF,&FF,&FF
BFF0 EQUB &FF,&FF,&FF,&FF
BFF4 EQUB &FF,&FF,&FF,&FF
BFF8 EQUB &FF,&FF,&FF,&FF
BFFC EQUB &FF,&FF,&FF,&FF
#else /* _DDOS316 */
;////////////////////////////////////////////// COMMON
.S673 ;Test write protect state
B673 20 3A B7 JSR S73A ;issue Seek and Force Interrupt
B676 20 03 BA JSR SA03 ;wait for command completion
B679 29 40 AND #&40 ;z=0 if WD1770 S6 = write protect.
B67B 60 RTS
;[BUG] The recalibrate and seek routines raise the INTRQ pin which
;causes an NMI, but do not install code at the NMI entry point.
;Any code left in the NMI area at &0D00 is executed.
;Typically there is an RTI instruction at &0D00 left by the MOS on
;reset, or by a previous NMI service routine that self-sealed. An FDC
;command that did not complete, however, leaves its ISR active and this
;services the NMI - treating the command completion interrupt as a data
;request - and interferes with the byte transfer count at &A0..1.
;A floppy disc operation performs a seek as a subtask after storing the
;count and before installing its service routine. It expects NMIs to be
;ignored in the meantime and because they are not, it goes on to
;transfer the wrong number of bytes.
;If re-entered, the RAM disc transfer code overwrites memory and crashes
;(original version; it is patched in this file under symbol _RAMBUGFIX.)
;Machines with Econet are also affected.
;Opus 2791/2793 board users (running DDOS 3.1x/3.3x) don't have their
;INTRQ pin connected to the NMI line and get off scot-free.
.S67C ;Recalibrate drive (seek track 0)
B67C 20 29 A3 JSR R329 ;save XY
B67F A9 00 LDA #&00 ;WD1770 FDC command &00 = Restore
# if defined _BUGFIX
B681 20 F6 92 JSR Q2F6 ;execute command and wait for completion
# else
B681 20 B9 B6 JSR S6B9 ;execute command and wait for completion
# endif
B684 A5 CF LDA &CF ;get current volume
B686 29 01 AND #&01 ;extract physical unit number 0/2 or 1/3
B688 AA TAX ;transfer to X for use as index
B689 A9 00 LDA #&00 ;set physical position of head to 0
B68B 9D 8C 10 STA &108C,X
B68E 60 RTS
.S68F ;Seek logical track
B68F A5 BA LDA &BA ;get logical track number
B691 2C E0 10 BIT &10E0 ;test double-stepping flag
B694 50 01 BVC S697 ;if b6=1 then double stepping is enabled
B696 0A ASL A ;so double track number:
.S697 ;Seek physical track
B697 C9 00 CMP #&00 ;if track number = 0
B699 F0 E1 BEQ S67C ;then issue Restore command
B69B 20 29 A3 JSR R329 ;else save XY
B69E 48 PHA ;save target physical track
B69F A5 CF LDA &CF ;get current volume
B6A1 29 01 AND #&01 ;extract physical unit number 0/2 or 1/3
B6A3 AA TAX ;transfer to X for use as index
B6A4 BD 8C 10 LDA &108C,X ;get physical track number for drive
B6A7 20 B2 B9 JSR S9B2 ;store in track register of FDC
B6AA 68 PLA ;restore target physical track
B6AB 9D 8C 10 STA &108C,X ;store physical track number for drive
B6AE 20 F7 B9 JSR S9F7 ;write to FDC data register
B6B1 A9 10 LDA #&10 ;WD1770 FDC command &10 = Seek
# if defined _BUGFIX
B6B3 20 F6 92 JSR Q2F6 ;execute command and wait for completion
# else
B6B3 20 B9 B6 JSR S6B9 ;execute command and wait for completion
# endif
B6B6 29 10 AND #&10 ;z=0 if WD1770 S4 = record not found.
B6B8 60 RTS
.S6B9 ;Execute Restore/Seek command
B6B9 0D 8E 10 ORA &108E ;apply track stepping rate
B6BC 20 EF B9 JSR S9EF ;write to FDC command register
B6BF 4C 03 BA JMP SA03 ;wait for command completion and exit.
.S6C2 ;Ensure disc is formatted
B6C2 20 CB B6 JSR S6CB ;read ID and detect density
B6C5 F0 03 BEQ S6CA ;if record found then exit
B6C7 4C D8 B9 JMP S9D8 ;else raise "Disk not formatted" error.
.S6CA
B6CA 60 RTS
.S6CB ;Read ID and detect density
B6CB 20 29 A3 JSR R329 ;save XY
B6CE 20 3A B7 JSR S73A ;issue Seek and Force Interrupt
B6D1 A2 04 LDX #&04 ;4 attempts to make, 2 in each density:
B6D3 2C E3 10 BIT &10E3 ;if current density is single
B6D6 50 0F BVC S6E7 ;then attempt in single density first, else:
.S6D8
B6D8 AD E3 10 LDA &10E3 ;get density flag
B6DB 09 40 ORA #&40 ;set b6=1, double density
B6DD A0 12 LDY #&12 ;18 sectors per track
B6DF 20 0C B7 JSR S70C ;execute Read Address at specified density
B6E2 F0 25 BEQ S709 ;if record found then return success
B6E4 CA DEX ;else decrement number of attempts remaining
B6E5 F0 0F BEQ S6F6 ;if run out of tries then return failure
.S6E7
B6E7 AD E3 10 LDA &10E3 ;else get density flag
B6EA 29 BF AND #&BF ;set b6=0, single density
B6EC A0 0A LDY #&0A ;10 sectors per track
B6EE 20 0C B7 JSR S70C ;execute Read Address at specified density
B6F1 F0 16 BEQ S709 ;if record found then return success
B6F3 CA DEX ;else decrement number of attempts remaining
B6F4 D0 E2 BNE S6D8 ;if attempts remaining try double density
.S6F6
B6F6 AD E3 10 LDA &10E3 ;else set b6=0, single density
B6F9 29 BF AND #&BF
B6FB 8D E3 10 STA &10E3
B6FE 20 58 B6 JSR S658 ;set control latch for drive
B701 A9 0A LDA #&0A ;set 10 sectors per track
B703 8D E1 10 STA &10E1
B706 A9 18 LDA #&18 ;fake WD1770 S4 = record not found
B708 60 RTS ;fake WD1770 S3 = CRC error.
.S709
B709 A9 00 LDA #&00 ;fake WD1770 status = 0, succeeded.
B70B 60 RTS
.S70C ;Execute Read Address at specified density
B70C 8D E3 10 STA &10E3 ;store density flag
B70F 8C E1 10 STY &10E1 ;store number of sectors per track:
.S712 ;Execute Read Address command
B712 A0 14 LDY #&14 ;21 bytes to copy, &0D00..14:
.S714
# if defined _DDOS346
B714 B9 70 BA LDA &BA70,Y ;get byte of NMI read ID
# else
B714 B9 6F BA LDA &BA6F,Y ;get byte of NMI read ID
# endif
B717 99 00 0D STA &0D00,Y ;store in NMI area
B71A 88 DEY ;loop until all bytes copied
B71B 10 F7 BPL S714
B71D A9 00 LDA #&00 ;initialise offset = 0
B71F 85 A0 STA &A0
B721 20 58 B6 JSR S658 ;set control latch for drive
B724 A9 C0 LDA #&C0 ;WD1770 command &C0 = Read address
B726 20 EF B9 JSR S9EF ;write to FDC command register
B729 20 03 BA JSR SA03 ;wait for command completion
B72C 48 PHA ;save exit status
B72D A0 03 LDY #&03 ;4 bytes to copy, &1090..3:
.S72F
B72F B9 90 10 LDA &1090,Y ;get CHRN byte of sector ID
B732 99 02 10 STA &1002,Y ;copy to workspace
B735 88 DEY ;loop until all bytes copied
B736 10 F7 BPL S72F
B738 68 PLA ;restore Read Address command status and exit
B739 60 RTS
.S73A
B73A A9 18 LDA #&18 ;WD1770 command &18 = Seek w/spin up
B73C 20 EF B9 JSR S9EF ;write to FDC command register
B73F A2 0F LDX #&0F ;wait 38.5 microseconds
.S741
B741 CA DEX
B742 D0 FD BNE S741
B744 A9 D0 LDA #&D0 ;WD1770 command &D0 = Force interrupt
B746 4C EF B9 JMP S9EF ;write to FDC command register and exit
.S749
B749 60 RTS
.S74A ;Verify track
B74A 20 29 A3 JSR R329 ;save XY
B74D A9 00 LDA #&00
B74F 85 BB STA &BB ;sector number = 0
B751 85 A0 STA &A0 ;whole number of sectors to transfer
B753 AD E1 10 LDA &10E1 ;get number of sectors per track
B756 85 A1 STA &A1 ;set number of sectors to transfer
B758 A9 04 LDA #&04 ;set call number to &04, verify data
B75A 8D 00 10 STA &1000
.S75D ;Transfer data to disc L2
B75D 20 29 A3 JSR R329 ;save XY
B760 20 D6 A7 JSR R7D6 ;set up for current drive
B763 A2 0A LDX #&0A ;wait 26 microseconds
.S765
B765 CA DEX
B766 D0 FD BNE S765
# if defined _DDOS356
B768 AD 28 FE LDA &FE28 ;load FDC status register
# elif defined _DDOS357
B768 AD 28 FE LDA &FE28 ;load FDC status register
# else
B768 AD 80 FE LDA &FE80 ;load FDC status register
# endif
B76B 48 PHA ;save status
B76C 20 8F B6 JSR S68F ;seek logical track
B76F A5 BA LDA &BA ;get logical track number
B771 20 A8 B9 JSR S9A8 ;store as physical position of head
B774 68 PLA ;restore status
B775 30 19 BMI S790 ;if WD1770 S7 = motor on then skip
B777 AD 00 10 LDA &1000 ;else get data transfer call number
B77A C9 01 CMP #&01 ;if writing to disc
B77C D0 12 BNE S790
B77E 48 PHA ;then save call number, 1
B77F A9 04 LDA #&04 ;set call number to &04, verify data
B781 8D 00 10 STA &1000
B784 A2 02 LDX #&02 ;execute floppy drive command twice:
.S786
B786 20 99 B7 JSR S799 ;execute verify data command L1
B789 CA DEX ;decrement counter
B78A D0 FA BNE S786 ;loop until two verify passes made
B78C 68 PLA ;restore call number.
B78D 8D 00 10 STA &1000
.S790
B790 20 99 B7 JSR S799 ;execute floppy drive command L1
B793 48 PHA ;save masked status
B794 20 A0 B9 JSR S9A0 ;store head position for this drive
B797 68 PLA ;restore masked status, setting Z
B798 60 RTS ;and exit
.S799 ;Execute floppy drive command L1
B799 20 29 A3 JSR R329 ;save XY
B79C A5 A0 LDA &A0 ;save ?&A0, ?&A1 on stack
B79E 48 PHA
B79F A5 A1 LDA &A1
B7A1 48 PHA
# if defined _BEEBEM
;Shoddy trick to get BeebEm to write the last byte of a track. DO NOT USE
B7A2 20 FC AB JSR RBFC ;copy NMI read from disc/polling loop to NMI
# else
B7A2 20 31 B8 JSR S831 ;copy NMI read from disc/polling loop to NMI
# endif
B7A5 AD 01 10 LDA &1001
B7A8 8D 2D 0D STA &0D2D
B7AB A5 A0 LDA &A0 ;increment MSB byte count if LSB >0
B7AD F0 02 BEQ S7B1 ;not rounding up, converting number format;
B7AF E6 A1 INC &A1 ;Z=1 from both DECs means zero reached
.S7B1
B7B1 AD 00 10 LDA &1000 ;get data transfer call number
B7B4 29 05 AND #&05 ;if call=0 or 2, read (deleted) data
B7B6 F0 14 BEQ S7CC ;then branch
B7B8 6A ROR A ;else if b2..0 = 1x0, A=&04 verify data
B7B9 B0 15 BCS S7D0
B7BB A9 4C LDA #&4C ;then instruction at &0D06 = JMP &0D11
B7BD 8D 06 0D STA &0D06 ;discard byte from FDC data register
B7C0 A9 11 LDA #&11
B7C2 8D 07 0D STA &0D07
B7C5 A9 0D LDA #&0D
B7C7 8D 08 0D STA &0D08
B7CA D0 10 BNE S7DC
.S7CC
B7CC A0 07 LDY #&07 ;if call=0 or 2, read (deleted) data
B7CE D0 09 BNE S7D9 ;then data address is located at &0D07.
.S7D0
B7D0 A9 00 LDA #&00 ;if b0=1, A=1 or 3 write (deleted) data
B7D2 85 A0 STA &A0 ;then clear ?&A0, write whole sectors
B7D4 20 3D B8 JSR S83D ;copy NMI write to disc to NMI area
B7D7 A0 04 LDY #&04 ;data address is located at &0D04
.S7D9
B7D9 20 07 B8 JSR S807 ;set data address in NMI ISR
.S7DC
B7DC A5 F4 LDA &F4 ;get DDOS ROM slot number
B7DE 8D 38 0D STA &0D38 ;save in NMI area
B7E1 A5 BB LDA &BB ;get start sector number
B7E3 20 F3 B9 JSR S9F3 ;write to FDC sector register
B7E6 AC 00 10 LDY &1000 ;get data transfer call number
# if defined _DDOS346
B7E9 B9 1B BA LDA &BA1B,Y ;get FDC command for call
# else
B7E9 B9 1A BA LDA &BA1A,Y ;get FDC command for call
# endif
B7EC 20 EF B9 JSR S9EF ;write to FDC command register
B7EF A2 1E LDX #&1E ;wait 76 microseconds
.S7F1
B7F1 CA DEX
B7F2 D0 FD BNE S7F1
B7F4 20 2C 0D JSR &0D2C ;page SROM in and wait until finished L0
B7F7 68 PLA ;restore ?&A0, ?&A1 from stack
B7F8 85 A1 STA &A1
B7FA 68 PLA
B7FB 85 A0 STA &A0
# if defined _DDOS346
B7FD 20 12 BA JSR SA12 ;load FDC status register and store b6..0
B800 AC 00 10 LDY &1000
B803 39 20 BA AND &BA20,Y ;apply status mask from table to set Z.
# else
B7FD 20 11 BA JSR SA11 ;load FDC status register and store b6..0
B800 AC 00 10 LDY &1000
B803 39 1F BA AND &BA1F,Y ;apply status mask from table to set Z.
# endif
B806 60 RTS
.S807 ;Set data address in NMI ISR
B807 AD D5 10 LDA &10D5 ;test Tube data transfer flag
B80A F0 1A BEQ S826 ;if transferring data to Tube
B80C A9 E5 LDA #&E5 ;then paste address of Tube FIFO 3 at &0D00+Y
B80E 99 00 0D STA &0D00,Y
B811 A9 FE LDA #&FE
B813 99 01 0D STA &0D01,Y
B816 A9 4C LDA #&4C ;instruction at &0D09 = JMP &0D11
B818 8D 09 0D STA &0D09 ;do not increment Tube FIFO 3 address
B81B A9 11 LDA #&11
B81D 8D 0A 0D STA &0D0A
B820 A9 0D LDA #&0D
B822 8D 0B 0D STA &0D0B
B825 60 RTS
.S826
B826 A5 A6 LDA &A6 ;else copy data pointer to NMI ISR at &0D00+Y
B828 99 00 0D STA &0D00,Y
B82B A5 A7 LDA &A7
B82D 99 01 0D STA &0D01,Y
B830 60 RTS
.S831 ;Copy NMI read from disc/polling loop to NMI
B831 A0 3C LDY #&3C ;61 bytes to copy, &0D00..3C:
.S833
# if defined _DDOS346
B833 B9 25 BA LDA &BA25,Y ;get byte of NMI read from disc/polling loop
# else
B833 B9 24 BA LDA &BA24,Y ;get byte of NMI read from disc/polling loop
# endif
B836 99 00 0D STA &0D00,Y ;store in NMI area
B839 88 DEY ;loop until all bytes copied
B83A 10 F7 BPL S833
B83C 60 RTS
.S83D ;Copy NMI write to disc to NMI area
B83D A0 0D LDY #&0D ;14 bytes to copy, &0D03..10:
.S83F
# if defined _DDOS346
B83F B9 62 BA LDA &BA62,Y ;get byte of NMI write to disc
# else
B83F B9 61 BA LDA &BA61,Y ;get byte of NMI write to disc
# endif
B842 99 03 0D STA &0D03,Y ;patch NMI read to disc routine with it
B845 88 DEY ;loop until all bytes copied
B846 10 F7 BPL S83F
B848 A9 FC LDA #&FC
B84A 8D 23 0D STA &0D23
B84D 60 RTS
.S84E
B84E A9 0A LDA #&0A ;set A = 10 sectors per track
B850 2C E3 10 BIT &10E3 ;if double density format
B853 50 02 BVC S857
B855 A9 12 LDA #&12 ;then set A = 18 sectors per track
.S857
B857 85 A6 STA &A6 ;store as limit to sector count
B859 0A ASL A ;multiply by 4
B85A 0A ASL A
B85B 85 A7 STA &A7 ;store as size of CHRN table
B85D A6 BB LDX &BB ;set X = number of first sector
B85F A0 00 LDY #&00 ;(inverse track skew) Y=0 CHRN tbl index
.S861
B861 A5 BA LDA &BA ;Get logical track number
B863 99 A0 11 STA &11A0,Y ;store cylinder number C
B866 C8 INY
B867 A9 00 LDA #&00 ;head number = 0
B869 99 A0 11 STA &11A0,Y ;store head humber H
B86C C8 INY
B86D 8A TXA ;transfer sector number to A
B86E 99 A0 11 STA &11A0,Y ;store record number R
B871 C8 INY
B872 A9 01 LDA #&01 ;size code = 1, 256-byte sector
B874 99 A0 11 STA &11A0,Y ;store size code N
B877 C8 INY
B878 E8 INX ;increment sector number
B879 E4 A6 CPX &A6 ;has it reached no. sectors per track?
B87B 90 02 BCC S87F
B87D A2 00 LDX #&00 ;if so then wrap around to 0
.S87F
B87F C4 A7 CPY &A7 ;has table offset reached 4x s.p.t?
B881 90 DE BCC S861 ;if not then loop
B883 A9 A0 LDA #&A0 ;else set pointer to start of CHRN table
B885 85 A6 STA &A6
B887 A9 11 LDA #&11
B889 85 A7 STA &A7
.S88B
B88B A9 12 LDA #&12 ;set data table pointer to &1312
B88D 85 A2 STA &A2 ;(page break occurs 1/8 of the way through
B88F 85 A4 STA &A4 ;the 11th sector of the track.)
B891 A9 13 LDA #&13
B893 85 A3 STA &A3
B895 A9 15 LDA #&15 ;set run table pointer to &1512
B897 85 A5 STA &A5
B899 A2 00 LDX #&00 ;point to single density table, X = &00
B89B 2C E3 10 BIT &10E3 ;if double density format
B89E 50 02 BVC S8A2
B8A0 A2 23 LDX #&23 ;then point to double density table, X = &23
.S8A2
B8A2 A0 05 LDY #&05 ;set Y = 5 as counter:
.S8A4
B8A4 20 E5 B8 JSR S8E5 ;add entry to track format RLE table
B8A7 88 DEY ;loop until 5 entries added
B8A8 D0 FA BNE S8A4 ;this copies gap 5, IDAM and start of gap 1
B8AA A0 0A LDY #&0A ;set Y = 10 sectors per track
B8AC 2C E3 10 BIT &10E3 ;if double density format
B8AF 50 02 BVC S8B3
B8B1 A0 12 LDY #&12 ;then Y = 18 sectors per track
.S8B3
B8B3 8A TXA ;X points to repeating sector block
B8B4 48 PHA ;save it
.S8B5
B8B5 20 E5 B8 JSR S8E5 ;add entry to track format RLE table
B8B8 90 FB BCC S8B5 ;loop until terminator byte reached
B8BA 68 PLA ;reset X to start of sector block
B8BB AA TAX
B8BC 88 DEY ;decrement number of sectors remaining
B8BD D0 F4 BNE S8B3 ;loop until all sectors added to track
B8BF A9 00 LDA #&00 ;data byte = &00 (run length = &10 or &16)
B8C1 20 38 B9 JSR S938 ;add gap 4 to table
B8C4 20 8F B6 JSR S68F ;seek logical track
B8C7 A9 0F LDA #&0F ;A = &0F (or just do LDY &1512:DEY:STY &A0!)
B8C9 2C E3 10 BIT &10E3 ;if double density format
B8CC 50 02 BVC S8D0
B8CE A9 27 LDA #&27 ;then A = &27
.S8D0
B8D0 85 A0 STA &A0 ;set number of filler bytes in gap 5 (- 1)
B8D2 A0 23 LDY #&23 ;36 bytes to copy, &0D00..23:
.S8D4
# if defined _DDOS346
B8D4 B9 85 BA LDA &BA85,Y ;get byte of NMI format code
# else
B8D4 B9 84 BA LDA &BA84,Y ;get byte of NMI format code
# endif
B8D7 99 00 0D STA &0D00,Y ;store in NMI handler area
B8DA 88 DEY ;loop until all bytes transferred
B8DB 10 F7 BPL S8D4
B8DD A9 F4 LDA #&F4 ;&F4=Write track, settling delay
B8DF 20 EF B9 JSR S9EF ;write to FDC command register
B8E2 4C 03 BA JMP SA03 ;wait for command completion and exit.
.S8E5 ;Add entry to track format RLE table
B8E5 8A TXA ;save ROM table offset
B8E6 48 PHA
B8E7 98 TYA ;save number of sectors remaining
B8E8 48 PHA
B8E9 A0 00 LDY #&00 ;y=&00, unused
B8EB 38 SEC
B8EC BD 56 B9 LDA &B956,X ;get run length from ROM table
B8EF 30 12 BMI S903 ;if b7=1 then process special entry
B8F1 F0 09 BEQ S8FC ;if the terminator byte then finish C=1
B8F3 85 A0 STA &A0 ;else store run length in zero page
B8F5 BD 57 B9 LDA &B957,X ;get data byte from ROM table
B8F8 20 38 B9 JSR S938 ;store run in table
.S8FB
B8FB 18 CLC ;C=0, sector not completed
.S8FC
B8FC 68 PLA ;restore number of sectors remaining
B8FD A8 TAY
B8FE 68 PLA ;restore ROM table offset
B8FF AA TAX
B900 E8 INX ;add 2 to ROM table offset
B901 E8 INX
B902 60 RTS
.S903 ;Process special table entry (length=&FF)
B903 BD 57 B9 LDA &B957,X ;get data byte from ROM format table
B906 D0 1C BNE S924 ;if non-zero then add sector data area
B908 A9 01 LDA #&01 ;else add ID bytes. run length of bytes = 1
B90A 85 A0 STA &A0 ;store run length in zero page
B90C A2 04 LDX #&04 ;4 bytes in sector ID:
.S90E
B90E A0 00 LDY #&00 ;Y=0 for user memory load
B910 20 15 9E JSR QE15 ;get data byte from user memory
B913 20 38 B9 JSR S938 ;store run in table
B916 E6 A6 INC &A6 ;increment CHRN table pointer
B918 D0 02 BNE S91C ;carry out to high byte
B91A E6 A7 INC &A7
.S91C
B91C CA DEX ;loop until 4 ID bytes stored
B91D D0 EF BNE S90E
B91F 85 A1 STA &A1 ;store last byte read = N = size code
B921 4C FB B8 JMP S8FB
.S924 ;Add sector data area
B924 A6 A1 LDX &A1 ;load sector size code
B926 BD 9C B9 LDA &B99C,X ;get run length from table
B929 85 A0 STA &A0 ;store in zero page
B92B A2 08 LDX #&08 ;repeat prescribed run 8 times:
.S92D
B92D A9 E5 LDA #&E5 ;A=&E5 = sector filler byte
B92F 20 38 B9 JSR S938 ;store run in table
B932 CA DEX ;loop until 8 copies of run stored
B933 D0 F8 BNE S92D
B935 4C FB B8 JMP S8FB
.S938 ;Store run in table
B938 A0 00 LDY #&00 ;offset = 0 for indirect indexed store
B93A 91 A2 STA (&A2),Y ;store data byte in data table
B93C A5 A0 LDA &A0 ;get run length
B93E 91 A4 STA (&A4),Y ;store run length in run table
B940 C6 A4 DEC &A4 ;if pointers are on a page boundary
B942 E6 A4 INC &A4
B944 D0 05 BNE S94B
B946 38 SEC ;then subtract 1 from run length
B947 E9 01 SBC #&01
B949 91 A4 STA (&A4),Y
.S94B
B94B E6 A2 INC &A2 ;increment data table pointer
B94D E6 A4 INC &A4 ;increment run table pointer
B94F D0 04 BNE S955 ;carry out to high bytes
B951 E6 A3 INC &A3
B953 E6 A5 INC &A5
.S955
B955 60 RTS
;RLE tables of formatting bytes
;Single density
B956 EQUB &10,&FF ; 16x &FF filler bytes } Gap 5
B958 EQUB &03,&00 ; 6x &00 synchronization bytes }
B95A EQUB &03,&00
B95C EQUB &01,&FC ; 1x &FC index address mark (clock &D7)
B95E EQUB &0B,&FF ; 11x &FF filler bytes } Gap 1
;block repeated for each sector
B960 EQUB &03,&00 ; 6x &00 synchronization bytes }
B962 EQUB &03,&00
B964 EQUB &01,&FE ; 1x &FE ID address mark (clock &C7)
B966 EQUB &FF,&00 ;id bytes are inserted here
B968 EQUB &01,&F7 ; 1x &F7 CRC character insert (2 bytes)
B96A EQUB &0B,&FF ; 11x &FF filler bytes } Gap 2
B96C EQUB &03,&00 ; 6x &00 synchronization bytes }
B96E EQUB &03,&00
B970 EQUB &01,&FB ; 1x &FB data address mark (clock &C7)
B972 EQUB &FF,&01 ;data bytes are inserted here
B974 EQUB &01,&F7 ; 1x &F7 CRC character insert (2 bytes)
B976 EQUB &10,&FF ; 16x &FF filler bytes } Gap 3...
;end of repeated block
B978 EQUB &00 ;terminator byte (not part of format)
;Double density
B979 EQUB &28,&4E ; 40x &4E filler bytes }
B97B EQUB &0C,&00 ; 12x &00 preamble bytes } Gap 5
B97D EQUB &03,&F6 ; 3x &F6 synchronization bytes }
B97F EQUB &01,&FC ; 1x &FC index address mark
B981 EQUB &19,&4E ; 25x &4E filler bytes } Gap 1
;block repeated for each sector
B983 EQUB &0C,&00 ; 12x &00 preamble bytes }
B985 EQUB &03,&F5 ; 3x &F5 synchronization bytes }
B987 EQUB &01,&FE ; 1x &FE ID address mark
B989 EQUB &FF,&00 ;id bytes are inserted here
B98B EQUB &01,&F7 ; 1x &F7 CRC character insert (2 bytes)
B98D EQUB &16,&4E ; 22x &4E filler bytes }
B98F EQUB &0C,&00 ; 12X &00 preamble bytes } Gap 2
B991 EQUB &03,&F5 ; 3x &F5 synchronization bytes }
B993 EQUB &01,&FB ; 1x &FB data address mark
B995 EQUB &FF,&01 ;data bytes are inserted here
B997 EQUB &01,&F7 ; 1x &F7 CRC character insert (2 bytes)
B999 EQUB &16,&4E ; 22x &4E filler bytes } Gap 3...
;end of repeated block
B99B EQUB &00 ;terminator byte (not part of format)
B99C EQUB &10 ;8x runs of 16 bytes for 128-byte sectors
B99D EQUB &20 ;8x runs of 32 bytes for 256-byte sectors
B99E EQUB &40 ;8x runs of 64 bytes for 512-byte sectors
B99F EQUB &80 ;8x runs of 128 bytes for 1024-byte sectors
.S9A0 ;Store per-drive head position
B9A0 A5 BA LDA &BA ;get logical track number of disc operation
B9A2 2C E0 10 BIT &10E0 ;test double-stepping flag
B9A5 50 01 BVC S9A8 ;if b6=1 then double stepping is enabled
B9A7 0A ASL A ;so double track number
.S9A8
B9A8 48 PHA
B9A9 A5 CF LDA &CF ;get current volume
B9AB 29 01 AND #&01 ;extract physical unit number 0/2 or 1/3
B9AD AA TAX ;transfer to X for use as index
B9AE 68 PLA ;get back A
B9AF 9D 8C 10 STA &108C,X ;store physical track number for drive
.S9B2
# if defined _DDOS356
B9B2 8D 29 FE STA &FE29 ;store in track register of FDC
# elif defined _DDOS357
B9B2 8D 29 FE STA &FE29 ;store in track register of FDC
# else
B9B2 8D 81 FE STA &FE81 ;store in track register of FDC
# endif
B9B5 60 RTS
.S9B6
B9B6 20 47 A3 JSR R347
B9B9 EQUB &C5
B9BA EQUS " fault"
B9C0 EQUB &00
B9C1 20 62 A3 JSR R362
B9C4 EQUB &C5
B9C5 EQUS "Cannot recalibrate"
B9D7 EQUB &00
.S9D8
B9D8 20 62 A3 JSR R362
B9DB EQUB &C5
B9DC EQUS "Disk not formatted"
B9EE EQUB &00
.S9EF ;Write to FDC command register
# if defined _DDOS356
B9EF 8D 28 FE STA &FE28
# elif defined _DDOS357
B9EF 8D 28 FE STA &FE28
# else
B9EF 8D 80 FE STA &FE80
# endif
B9F2 60 RTS
.S9F3 ;Write to FDC sector register
# if defined _DDOS356
B9F3 8D 2A FE STA &FE2A
# elif defined _DDOS357
B9F3 8D 2A FE STA &FE2A
# else
B9F3 8D 82 FE STA &FE82
# endif
B9F6 60 RTS
.S9F7 ;Write to FDC data register
# if defined _DDOS356
B9F7 8D 2B FE STA &FE2B
# elif defined _DDOS357
B9F7 8D 2B FE STA &FE2B
# else
B9F7 8D 83 FE STA &FE83
# endif
B9FA 60 RTS
.S9FB ;Load FDC status register
# if defined _DDOS356
B9FB AD 28 FE LDA &FE28
# elif defined _DDOS357
B9FB AD 28 FE LDA &FE28
# else
B9FB AD 80 FE LDA &FE80
# endif
B9FE 29 80 AND #&80 ;mask b7 extract WD1770 S7 = motor on
BA00 49 80 EOR #&80 ;return A=0, Z=1 iff motor is on
BA02 60 RTS
# if defined _DDOS346
;////////////////////////////////////////////// DDOS 3.46
.SA03
BA03 20 29 A3 JSR R329 ;save XY
BA06 A2 FF LDX #&FF
.SA08
BA08 CA DEX
BA09 D0 FD BNE SA08
.SA0B
BA0B 20 12 BA JSR SA12
BA0E 29 01 AND #&01
BA10 D0 F9 BNE SA0B
.SA12
BA12 AD 80 FE LDA &FE80
BA15 29 7F AND #&7F
BA17 8D 8F 10 STA &108F
BA1A 60 RTS
BA1B EQUB &90
BA1C EQUB &B4
BA1D EQUB &90
BA1E EQUB &B5
BA1F EQUB &90
BA20 EQUB &3C
BA21 EQUB &7C
BA22 EQUB &1C
BA23 EQUB &5C
BA24 EQUB &3C
BA25 8D 2A 0D STA &0D2A
BA28 AD 83 FE LDA &FE83
BA2B 8D FF FF STA &FFFF
BA2E EE 07 0D INC &0D07
BA31 D0 03 BNE SA36
BA33 EE 08 0D INC &0D08
.SA36
BA36 C6 A0 DEC &A0
BA38 D0 14 BNE SA4E
BA3A C6 A1 DEC &A1
BA3C D0 10 BNE SA4E
BA3E A9 40 LDA #&40
BA40 8D 00 0D STA &0D00
BA43 A9 CE LDA #&CE
BA45 69 01 ADC #&01
BA47 90 00 BCC SA49
.SA49
BA49 A9 D0 LDA #&D0
BA4B 8D 80 FE STA &FE80
.SA4E
BA4E A9 00 LDA #&00
BA50 40 RTI
BA51 A9 0E LDA #&0E
BA53 8D 30 FE STA &FE30
.SA56
BA56 AD 80 FE LDA &FE80
BA59 6A ROR A
BA5A B0 FA BCS SA56
BA5C A9 00 LDA #&00
BA5E 8D 30 FE STA &FE30
BA61 60 RTS
BA62 AD FF FF LDA &FFFF
BA65 8D 83 FE STA &FE83
BA68 EE 04 0D INC &0D04
BA6B D0 03 BNE SA70
BA6D EE 05 0D INC &0D05
.SA70
BA70 8D 13 0D STA &0D13
BA73 8C 11 0D STY &0D11
BA76 A4 A0 LDY &A0
BA78 AD 83 FE LDA &FE83
BA7B 99 90 10 STA &1090,Y
BA7E E6 A0 INC &A0
BA80 A0 00 LDY #&00
BA82 A9 00 LDA #&00
BA84 40 RTI
BA85 48 PHA
BA86 AD 12 13 LDA &1312
BA89 8D 83 FE STA &FE83
BA8C C6 A0 DEC &A0
BA8E D0 0A BNE SA9A
BA90 EE 02 0D INC &0D02
BA93 D0 0A BNE SA9F
BA95 EE 03 0D INC &0D03
.SA98
BA98 68 PLA
BA99 40 RTI
.SA9A
BA9A 10 FC BPL SA98
BA9C EE 1F 0D INC &0D1F
.SA9F
BA9F EE 1E 0D INC &0D1E
BAA2 AD 12 15 LDA &1512
BAA5 85 A0 STA &A0
BAA7 68 PLA
BAA8 40 RTI
BAA9 EA NOP
.SAAA
BAAA C9 FE CMP #&FE
BAAC 90 5C BCC SB0A
BAAE D0 1B BNE SACB
BAB0 C0 00 CPY #&00
BAB2 F0 56 BEQ SB0A
BAB4 A2 06 LDX #&06
BAB6 A9 14 LDA #&14
BAB8 20 F4 FF JSR &FFF4
.SABB
BABB 2C E0 FE BIT &FEE0
BABE 10 FB BPL SABB
BAC0 AD E1 FE LDA &FEE1
BAC3 F0 43 BEQ SB08
BAC5 20 EE FF JSR &FFEE
BAC8 4C BB BA JMP SABB
.SACB
BACB A9 AD LDA #&AD
BACD 8D 20 02 STA &0220
BAD0 A9 06 LDA #&06
BAD2 8D 21 02 STA &0221
BAD5 A9 16 LDA #&16
BAD7 8D 02 02 STA &0202
BADA A9 00 LDA #&00
BADC 8D 03 02 STA &0203
BADF A9 8E LDA #&8E
BAE1 8D E0 FE STA &FEE0
BAE4 A0 00 LDY #&00
.SAE6
BAE6 B9 4C BB LDA &BB4C,Y
BAE9 99 00 04 STA &0400,Y
BAEC B9 4C BC LDA &BC4C,Y
BAEF 99 00 05 STA &0500,Y
BAF2 B9 4C BD LDA &BD4C,Y
BAF5 99 00 06 STA &0600,Y
BAF8 88 DEY
BAF9 D0 EB BNE SAE6
BAFB 20 21 04 JSR &0421
BAFE A2 60 LDX #&60
.SB00
BB00 BD 0B BB LDA &BB0B,X
BB03 95 16 STA &16,X
BB05 CA DEX
BB06 10 F8 BPL SB00
.SB08
BB08 A9 00 LDA #&00
.SB0A
BB0A 60 RTS
BB0B A9 FF LDA #&FF
BB0D 20 9E 06 JSR &069E
BB10 AD E3 FE LDA &FEE3
BB13 A9 00 LDA #&00
BB15 20 95 06 JSR &0695
BB18 A8 TAY
BB19 B1 FD LDA (&FD),Y
BB1B 20 95 06 JSR &0695
.SB1E
BB1E C8 INY
BB1F B1 FD LDA (&FD),Y
BB21 20 95 06 JSR &0695
BB24 AA TAX
BB25 D0 F7 BNE SB1E
BB27 A2 FF LDX #&FF
BB29 9A TXS
BB2A 58 CLI
.SB2B
BB2B 2C E0 FE BIT &FEE0
BB2E 10 06 BPL SB36
.SB30
BB30 AD E1 FE LDA &FEE1
BB33 20 EE FF JSR &FFEE
.SB36
BB36 2C E2 FE BIT &FEE2
BB39 10 F0 BPL SB2B
BB3B 2C E0 FE BIT &FEE0
BB3E 30 F0 BMI SB30
BB40 AE E3 FE LDX &FEE3
BB43 86 51 STX &51
BB45 6C 00 05 JMP (&0500)
BB48 EQUB &00
BB49 EQUB &80
BB4A EQUB &00
BB4B EQUB &00
BB4C 4C 84 04 JMP &0484
BB4F 4C A7 06 JMP &06A7
BB52 C9 80 CMP #&80
BB54 90 2B BCC SB81
BB56 C9 C0 CMP #&C0
BB58 B0 1A BCS SB74
BB5A 09 40 ORA #&40
BB5C C5 15 CMP &15
BB5E D0 20 BNE SB80
BB60 08 PHP
BB61 78 SEI
BB62 A9 05 LDA #&05
BB64 20 9E 06 JSR &069E
BB67 A5 15 LDA &15
BB69 20 9E 06 JSR &069E
BB6C 28 PLP
BB6D A9 80 LDA #&80
BB6F 85 15 STA &15
BB71 85 14 STA &14
BB73 60 RTS
.SB74
BB74 06 14 ASL &14
BB76 B0 06 BCS SB7E
BB78 C5 15 CMP &15
BB7A F0 04 BEQ SB80
BB7C 18 CLC
BB7D 60 RTS
.SB7E
BB7E 85 15 STA &15
.SB80
BB80 60 RTS
.SB81
BB81 08 PHP
BB82 78 SEI
BB83 84 13 STY &13
BB85 86 12 STX &12
BB87 20 9E 06 JSR &069E
BB8A AA TAX
BB8B A0 03 LDY #&03
BB8D A5 15 LDA &15
BB8F 20 9E 06 JSR &069E
.SB92
BB92 B1 12 LDA (&12),Y
BB94 20 9E 06 JSR &069E
BB97 88 DEY
BB98 10 F8 BPL SB92
BB9A A0 18 LDY #&18
BB9C 8C E0 FE STY &FEE0
BB9F BD 18 05 LDA &0518,X
BBA2 8D E0 FE STA &FEE0
BBA5 4A LSR A
BBA6 4A LSR A
BBA7 90 06 BCC SBAF
BBA9 2C E5 FE BIT &FEE5
BBAC 2C E5 FE BIT &FEE5
.SBAF
BBAF 20 9E 06 JSR &069E
.SBB2
BBB2 2C E6 FE BIT &FEE6
BBB5 50 FB BVC SBB2
BBB7 B0 0D BCS SBC6
BBB9 E0 04 CPX #&04
BBBB D0 11 BNE SBCE
.SBBD
BBBD 20 14 04 JSR &0414
BBC0 20 95 06 JSR &0695
BBC3 4C 32 00 JMP &0032
.SBC6
BBC6 4A LSR A
BBC7 90 05 BCC SBCE
BBC9 A0 88 LDY #&88
BBCB 8C E0 FE STY &FEE0
.SBCE
BBCE 28 PLP
BBCF 60 RTS
BBD0 58 CLI
BBD1 B0 11 BCS SBE4
BBD3 D0 03 BNE SBD8
BBD5 4C 9C 05 JMP &059C
.SBD8
BBD8 A2 00 LDX #&00
BBDA A0 FF LDY #&FF
BBDC A9 FD LDA #&FD
BBDE 20 F4 FF JSR &FFF4
BBE1 8A TXA
BBE2 F0 D9 BEQ SBBD
.SBE4
BBE4 A9 FF LDA #&FF
BBE6 20 06 04 JSR &0406
BBE9 90 F9 BCC SBE4
BBEB 20 D2 04 JSR &04D2
.SBEE
BBEE A9 07 LDA #&07
BBF0 20 CB 04 JSR &04CB
BBF3 A0 00 LDY #&00
BBF5 84 00 STY &00
.SBF7
BBF7 B1 00 LDA (&00),Y
BBF9 8D E5 FE STA &FEE5
BBFC EA NOP
BBFD EA NOP
BBFE EA NOP
BBFF C8 INY
BC00 D0 F5 BNE SBF7
BC02 E6 54 INC &54
BC04 D0 06 BNE SC0C
BC06 E6 55 INC &55
BC08 D0 02 BNE SC0C
BC0A E6 56 INC &56
.SC0C
BC0C E6 01 INC &01
BC0E 24 01 BIT &01
BC10 50 DC BVC SBEE
BC12 20 D2 04 JSR &04D2
BC15 A9 04 LDA #&04
BC17 A0 00 LDY #&00
BC19 A2 53 LDX #&53
BC1B 4C 06 04 JMP &0406
BC1E A9 80 LDA #&80
BC20 85 54 STA &54
BC22 85 01 STA &01
BC24 A9 20 LDA #&20
BC26 2D 06 80 AND &8006
BC29 A8 TAY
BC2A 84 53 STY &53
BC2C F0 19 BEQ SC47
BC2E AE 07 80 LDX &8007
.SC31
BC31 E8 INX
BC32 BD 00 80 LDA &8000,X
BC35 D0 FA BNE SC31
BC37 BD 01 80 LDA &8001,X
BC3A 85 53 STA &53
BC3C BD 02 80 LDA &8002,X
BC3F 85 54 STA &54
BC41 BC 03 80 LDY &8003,X
BC44 BD 04 80 LDA &8004,X
.SC47
BC47 85 56 STA &56
BC49 84 55 STY &55
BC4B 60 RTS
BC4C EQUW &37,&05
BC4E EQUW &96,&05
BC50 EQUW &F2,&05
BC52 EQUW &07,&06
BC54 EQUW &27,&06
BC56 EQUW &68,&06
BC58 EQUW &5E,&05
BC5A EQUW &2D,&05
BC5C EQUW &20,&05
BC5E EQUW &42,&05
BC60 EQUW &A9,&05
BC62 EQUW &D1,&05
BC64 EQUB &86
BC65 EQUB &88
BC66 EQUB &96
BC67 EQUB &98
BC68 EQUB &18
BC69 EQUB &18
BC6A EQUB &82
BC6B EQUB &18
BC6C 20 C5 06 JSR &06C5
BC6F A8 TAY
BC70 20 C5 06 JSR &06C5
BC73 20 D4 FF JSR &FFD4
BC76 4C 9C 05 JMP &059C
BC79 20 C5 06 JSR &06C5
BC7C A8 TAY
BC7D 20 D7 FF JSR &FFD7
BC80 4C 3A 05 JMP &053A
BC83 20 E0 FF JSR &FFE0
BC86 6A ROR A
BC87 20 95 06 JSR &0695
BC8A 2A ROL A
BC8B 4C 9E 05 JMP &059E
BC8E 20 C5 06 JSR &06C5
BC91 F0 0B BEQ SC9E
BC93 48 PHA
BC94 20 82 05 JSR &0582
BC97 68 PLA
BC98 20 CE FF JSR &FFCE
BC9B 4C 9E 05 JMP &059E
.SC9E
BC9E 20 C5 06 JSR &06C5
BCA1 A8 TAY
BCA2 A9 00 LDA #&00
BCA4 20 CE FF JSR &FFCE
BCA7 4C 9C 05 JMP &059C
BCAA 20 C5 06 JSR &06C5
BCAD A8 TAY
BCAE A2 04 LDX #&04
.SCB0
BCB0 20 C5 06 JSR &06C5
BCB3 95 FF STA &FF,X
BCB5 CA DEX
BCB6 D0 F8 BNE SCB0
BCB8 20 C5 06 JSR &06C5
BCBB 20 DA FF JSR &FFDA
BCBE 20 95 06 JSR &0695
BCC1 A2 03 LDX #&03
.SCC3
BCC3 B5 00 LDA &00,X
BCC5 20 95 06 JSR &0695
BCC8 CA DEX
BCC9 10 F8 BPL SCC3
BCCB 4C 36 00 JMP &0036
BCCE A2 00 LDX #&00
BCD0 A0 00 LDY #&00
.SCD2
BCD2 20 C5 06 JSR &06C5
BCD5 99 00 07 STA &0700,Y
BCD8 C8 INY
BCD9 F0 04 BEQ SCDF
BCDB C9 0D CMP #&0D
BCDD D0 F3 BNE SCD2
.SCDF
BCDF A0 07 LDY #&07
BCE1 60 RTS
BCE2 20 82 05 JSR &0582
BCE5 20 F7 FF JSR &FFF7
BCE8 A9 7F LDA #&7F
.SCEA
BCEA 2C E2 FE BIT &FEE2
BCED 50 FB BVC SCEA
BCEF 8D E3 FE STA &FEE3
.SCF2
BCF2 4C 36 00 JMP &0036
BCF5 A2 10 LDX #&10
.SCF7
BCF7 20 C5 06 JSR &06C5
BCFA 95 01 STA &01,X
BCFC CA DEX
BCFD D0 F8 BNE SCF7
BCFF 20 82 05 JSR &0582
BD02 86 00 STX &00
BD04 84 01 STY &01
BD06 A0 00 LDY #&00
BD08 20 C5 06 JSR &06C5
BD0B 20 DD FF JSR &FFDD
BD0E 20 95 06 JSR &0695
BD11 A2 10 LDX #&10
.SD13
BD13 B5 01 LDA &01,X
BD15 20 95 06 JSR &0695
BD18 CA DEX
BD19 D0 F8 BNE SD13
BD1B F0 D5 BEQ SCF2
BD1D A2 0D LDX #&0D
.SD1F
BD1F 20 C5 06 JSR &06C5
BD22 95 FF STA &FF,X
BD24 CA DEX
BD25 D0 F8 BNE SD1F
BD27 20 C5 06 JSR &06C5
BD2A A0 00 LDY #&00
BD2C 20 D1 FF JSR &FFD1
BD2F 48 PHA
BD30 A2 0C LDX #&0C
.SD32
BD32 B5 00 LDA &00,X
BD34 20 95 06 JSR &0695
BD37 CA DEX
BD38 10 F8 BPL SD32
BD3A 68 PLA
BD3B 4C 3A 05 JMP &053A
BD3E 20 C5 06 JSR &06C5
BD41 AA TAX
BD42 20 C5 06 JSR &06C5
BD45 20 F4 FF JSR &FFF4
.SD48
BD48 2C E2 FE BIT &FEE2
BD4B 50 FB BVC SD48
BD4D 8E E3 FE STX &FEE3
.SD50
BD50 4C 36 00 JMP &0036
BD53 20 C5 06 JSR &06C5
BD56 AA TAX
BD57 20 C5 06 JSR &06C5
BD5A A8 TAY
BD5B 20 C5 06 JSR &06C5
BD5E 20 F4 FF JSR &FFF4
BD61 49 9D EOR #&9D
BD63 F0 EB BEQ SD50
BD65 6A ROR A
BD66 20 95 06 JSR &0695
.SD69
BD69 2C E2 FE BIT &FEE2
BD6C 50 FB BVC SD69
BD6E 8C E3 FE STY &FEE3
BD71 70 D5 BVS SD48
BD73 20 C5 06 JSR &06C5
BD76 A8 TAY
.SD77
BD77 2C E2 FE BIT &FEE2
BD7A 10 FB BPL SD77
BD7C AE E3 FE LDX &FEE3
BD7F CA DEX
BD80 30 0F BMI SD91
.SD82
BD82 2C E2 FE BIT &FEE2
BD85 10 FB BPL SD82
BD87 AD E3 FE LDA &FEE3
BD8A 9D 28 01 STA &0128,X
BD8D CA DEX
BD8E 10 F2 BPL SD82
BD90 98 TYA
.SD91
BD91 A2 28 LDX #&28
BD93 A0 01 LDY #&01
BD95 20 F1 FF JSR &FFF1
.SD98
BD98 2C E2 FE BIT &FEE2
BD9B 10 FB BPL SD98
BD9D AE E3 FE LDX &FEE3
BDA0 CA DEX
BDA1 30 0E BMI SDB1
.SDA3
BDA3 BC 28 01 LDY &0128,X
.SDA6
BDA6 2C E2 FE BIT &FEE2
BDA9 50 FB BVC SDA6
BDAB 8C E3 FE STY &FEE3
BDAE CA DEX
BDAF 10 F2 BPL SDA3
.SDB1
BDB1 4C 36 00 JMP &0036
BDB4 A2 04 LDX #&04
.SDB6
BDB6 20 C5 06 JSR &06C5
BDB9 95 00 STA &00,X
BDBB CA DEX
BDBC 10 F8 BPL SDB6
BDBE E8 INX
BDBF A0 00 LDY #&00
BDC1 8A TXA
BDC2 20 F1 FF JSR &FFF1
BDC5 90 05 BCC SDCC
BDC7 A9 FF LDA #&FF
BDC9 4C 9E 05 JMP &059E
.SDCC
BDCC A2 00 LDX #&00
BDCE A9 7F LDA #&7F
BDD0 20 95 06 JSR &0695
.SDD3
BDD3 BD 00 07 LDA &0700,X
BDD6 20 95 06 JSR &0695
BDD9 E8 INX
BDDA C9 0D CMP #&0D
BDDC D0 F5 BNE SDD3
BDDE 4C 36 00 JMP &0036
.SDE1
BDE1 2C E2 FE BIT &FEE2
BDE4 50 FB BVC SDE1
BDE6 8D E3 FE STA &FEE3
BDE9 60 RTS
.SDEA
BDEA 2C E6 FE BIT &FEE6
BDED 50 FB BVC SDEA
BDEF 8D E7 FE STA &FEE7
BDF2 60 RTS
BDF3 A5 FF LDA &FF
BDF5 38 SEC
BDF6 6A ROR A
BDF7 30 0F BMI SE08
BDF9 48 PHA
BDFA A9 00 LDA #&00
BDFC 20 BC 06 JSR &06BC
BDFF 98 TYA
BE00 20 BC 06 JSR &06BC
BE03 8A TXA
BE04 20 BC 06 JSR &06BC
BE07 68 PLA
.SE08
BE08 2C E0 FE BIT &FEE0
BE0B 50 FB BVC SE08
BE0D 8D E1 FE STA &FEE1
BE10 60 RTS
.SE11
BE11 2C E2 FE BIT &FEE2
BE14 10 FB BPL SE11
BE16 AD E3 FE LDA &FEE3
BE19 60 RTS
.SE1A
BE1A 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
BE1D EQUB &83 ;yellow alphanumerics
BE1E EQUB &8D ;double height
BE1F EQUS " C O P Y R I G H T N O T I C E"
BE3F EQUB &0D
BE40 EQUB &0A
BE41 EQUB &FF
BE42 60 RTS
;*COPYRIGHT
BE43 20 74 AD JSR RD74 ;set display MODE 7
BE46 20 67 84 JSR P467 ;print newline
BE49 20 1A BE JSR SE1A
BE4C 20 1A BE JSR SE1A
BE4F 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
BE52 EQUB &0D
BE53 EQUB &0A
BE54 EQUB &0A
BE55 EQUS "This Double Density Operating System"
BE79 EQUB &0D
BE7A EQUB &0A
BE7B EQUS "was developed for the BBC computer by"
BEA0 EQUB &0D
BEA1 EQUB &0A
BEA2 EQUB &83 ;yellow alphanumerics
BEA3 EQUS "SLOGGER SOFTWARE and OPUS SUPPLIES"
BEC5 EQUB &0D
BEC6 EQUB &0A
BEC7 EQUS "Any unauthorised copying of this"
BEE7 EQUB &0D
BEE8 EQUB &0A
BEE9 EQUS "product is unlawful and may result in"
BF0E EQUB &0D
BF0F EQUB &0A
BF10 EQUS "Slogger or Opus taking appropriate"
BF32 EQUB &0D
BF33 EQUB &0A
BF34 EQUS "action."
BF3B EQUB &0D
BF3C EQUB &0A
BF3D EQUB &0A
BF3E EQUB &FF
BF3F 60 RTS
BF80 EQUB &FF,&FF,&FF,&FF
BF84 EQUB &FF,&FF,&FF,&FF
BF88 EQUB &FF,&FF,&FF,&FF
BF8C EQUB &FF,&FF,&FF,&FF
BF90 EQUB &FF,&FF,&FF,&FF
BF94 EQUB &FF,&FF,&FF,&FF
BF98 EQUB &FF,&FF,&FF,&FF
BF9C EQUB &FF,&FF,&FF,&FF
BFA0 EQUB &FF,&FF,&FF,&FF
BFA4 EQUB &FF,&FF,&FF,&FF
BFA8 EQUB &FF,&FF,&FF,&FF
BFAC EQUB &FF,&FF,&FF,&FF
BFB0 EQUB &FF,&FF,&FF,&FF
BFB4 EQUB &FF,&FF,&FF,&FF
BFB8 EQUB &FF,&FF,&FF,&FF
BFBC EQUB &FF,&FF,&FF,&FF
BFC0 EQUB &FF,&FF,&FF,&FF
BFC4 EQUB &FF,&FF,&FF,&FF
BFC8 EQUB &FF,&FF,&FF,&FF
BFCC EQUB &FF,&FF,&FF,&FF
BFD0 EQUB &FF,&FF,&FF,&FF
BFD4 EQUB &FF,&FF,&FF,&FF
BFD8 EQUB &FF,&FF,&FF,&FF
BFDC EQUB &FF,&FF,&FF,&FF
BFE0 EQUB &FF,&FF,&FF,&FF
BFE4 EQUB &FF,&FF,&FF,&FF
BFE8 EQUB &FF,&FF,&FF,&FF
BFEC EQUB &FF,&FF,&FF,&FF
BFF0 EQUB &FF,&FF,&FF,&FF
BFF4 EQUB &FF,&FF,&FF,&FF
BFF8 EQUB &FF,&FF,&FF,&FF
BFFC EQUB &FF,&FF,&FF,&FF
# else /* _DDOS346 */
;////////////////////////////////////////////// COMMON
.SA03
BA03 20 29 A3 JSR R329 ;save XY
BA06 A2 FF LDX #&FF ;wait 638.5 microseconds
.SA08
BA08 CA DEX
BA09 D0 FD BNE SA08
.SA0B
BA0B 20 11 BA JSR SA11 ;load FDC status register
BA0E 6A ROR A ;place bit 0 in carry flag
BA0F B0 FA BCS SA0B ;loop until b0=0 WD1770 S0 = busy
.SA11
# if defined _DDOS356
BA11 AD 28 FE LDA &FE28 ;load FDC status register
# elif defined _DDOS357
BA11 AD 28 FE LDA &FE28 ;load FDC status register
# else
BA11 AD 80 FE LDA &FE80 ;load FDC status register
# endif
BA14 29 7F AND #&7F ;mask bits 6..0 ignore WD1770 S7 = motor on
BA16 8D 8F 10 STA &108F
BA19 60 RTS
;Table of WD1770 FDC commands for data transfer call numbers 0..4
BA1A EQUB &90 ;&00 = Read data
BA1B EQUB &B4 ;&01 = Write data
BA1C EQUB &90
BA1D EQUB &B5 ;&03 = Write deleted data
BA1E EQUB &90 ;&04 = Verify data
;Table of status mask bytes for data transfer call numbers 0..4
;{RecordNotFound CRCError LostData} (&1C) plus:
BA1F EQUB &3C ;&00 = Read data: {RecordType}
BA20 EQUB &7C ;&01 = Write data: {WriteProtect RecordType}
BA21 EQUB &1C ;{}
BA22 EQUB &5C ;&03 = Write deleted data: {WriteProtect}
BA23 EQUB &3C ;&04 = Verify data: {RecordType}
;NMI read from disc, &0D00..2B
;opcode read 4+e..8 microseconds after NMI
;(up to 13.5 us if code running in 1 MHz mem)
BA24 8D 2A 0D STA &0D2A ;save accumulator to restore on exit
# if defined _DDOS356
BA27 AD 2B FE LDA &FE2B ;read FDC data register
# elif defined _DDOS357
BA27 AD 2B FE LDA &FE2B ;read FDC data register
# else
BA27 AD 83 FE LDA &FE83 ;read FDC data register
# endif
BA2A 8D FF FF STA &FFFF ;store in user memory or Tube FIFO 3
BA2D EE 07 0D INC &0D07 ;increment user memory address
BA30 D0 03 BNE SA35
BA32 EE 08 0D INC &0D08 ;carry out to high byte
.SA35
BA35 C6 A0 DEC &A0 ;decrement count of bytes to transfer
BA37 D0 14 BNE SA4D ;(&0101 = 1; &0000 = 0)
BA39 C6 A1 DEC &A1 ;if count has not reached zero
BA3B D0 10 BNE SA4D ;then restore A and return from interrupt
BA3D A9 40 LDA #&40 ;else set 0D00=RTI; ignore further NMIs
# if defined _BEEBEM
;Shoddy trick to get BeebEm to write the last byte of a track. DO NOT USE
;ISR seals itself too late, real hardware may read one excess byte at DD
BA3F 20 3D 0D JSR &0D3D ;call trampoline and come back with an RTI
;ISR safe by 25+e..32.5 us after NMI
;write complete by 27.5+e..35 us
BA42 EQUW &41,&0D ;does ORA &0D41; A=&CE
# else
BA3F 8D 00 0D STA &0D00 ;ISR safe by 22+e..29.5 us after NMI
;write complete by 24.5+e..32 us
BA42 A9 CE LDA #&CE ;wait 123 microseconds (if loop enabled)
# endif
BA44 69 01 ADC #&01
BA46 90 00 BCC SA48 ;0D23=&FC loops back to &0D20
.SA48
BA48 A9 D0 LDA #&D0 ;FDC command &D0 = Force Interrupt
# if defined _DDOS356
BA4A 8D 28 FE STA &FE28 ;write to FDC command register
# elif defined _DDOS357
BA4A 8D 28 FE STA &FE28 ;write to FDC command register
# else
BA4A 8D 80 FE STA &FE80 ;write to FDC command register
# endif
.SA4D
BA4D A9 00 LDA #&00 ;restore value of A on entry
BA4F 40 RTI ;return from interrupt
BA50 A9 0E LDA #&0E ;NMI polling loop, &0D2C..3C
BA52 8D 30 FE STA &FE30 ;page *SROM slot in
.SA55
# if defined _DDOS356
BA55 AD 28 FE LDA &FE28 ;load FDC status register
# elif defined _DDOS357
BA55 AD 28 FE LDA &FE28 ;load FDC status register
# else
BA55 AD 80 FE LDA &FE80 ;load FDC status register
# endif
BA58 6A ROR A ;place bit 0 in carry flag
BA59 B0 FA BCS SA55 ;loop until b0=0 WD1770 S0 = busy
BA5B A9 00 LDA #&00 ;page DDOS ROM back in
BA5D 8D 30 FE STA &FE30
BA60 60 RTS
BA61 AD FF FF LDA &FFFF ;NMI write to disc, &0D03..10
# if defined _DDOS356
BA64 8D 2B FE STA &FE2B
# elif defined _DDOS357
BA64 8D 2B FE STA &FE2B
# else
BA64 8D 83 FE STA &FE83
# endif
BA67 EE 04 0D INC &0D04
BA6A D0 03 BNE SA6F
BA6C EE 05 0D INC &0D05
.SA6F
BA6F 8D 13 0D STA &0D13 ;NMI read ID, &0D00..14
BA72 8C 11 0D STY &0D11 ;save AY to restore on exit
BA75 A4 A0 LDY &A0 ;load offset in Y
# if defined _DDOS356
BA77 AD 2B FE LDA &FE2B ;load FDC data register
# elif defined _DDOS357
BA77 AD 2B FE LDA &FE2B ;load FDC data register
# else
BA77 AD 83 FE LDA &FE83 ;load FDC data register
# endif
BA7A 99 90 10 STA &1090,Y ;store ID byte in buffer
BA7D E6 A0 INC &A0 ;increment offset
BA7F A0 00 LDY #&00 ;restore AY on entry
BA81 A9 00 LDA #&00
BA83 40 RTI
;A run-length encoded table of formatting bytes is stored in two arrays
;starting at &1312 and &1512. Valid range of counts is &01..&80.
;When the byte source address crosses a page, the high byte is incremented
;in the same interrupt and the new count is fetched (from the next page)
;in the next interrupt. One byte from the next page is sent to the
;controller in the meantime, and so the first count of a page is one less
;than the number of bytes actually sent, i.e. the first byte of the page
;cannot be a singleton. The page crossing occurs 1/8th of the way through
;the data area of the eleventh sector after the index pulse.
BA84 48 PHA ;NMI format, &0D00..23
BA85 AD 12 13 LDA &1312 ;save A on entry, fetch current data byte
# if defined _DDOS356
BA88 8D 2B FE STA &FE2B ;write to FDC data register
# elif defined _DDOS357
BA88 8D 2B FE STA &FE2B ;write to FDC data register
# else
BA88 8D 83 FE STA &FE83 ;write to FDC data register
# endif
BA8B C6 A0 DEC &A0 ;decrement run counter
BA8D D0 0A BNE SA99 ;if all bytes in run written
BA8F EE 02 0D INC &0D02 ;then increment data byte address low
BA92 D0 0A BNE SA9E ;if no carry then fetch next run length
BA94 EE 03 0D INC &0D03 ;else increment data byte address high
.SA97
BA97 68 PLA ;restore A on entry
BA98 40 RTI ;exit
.SA99
BA99 10 FC BPL SA97 ;if run still in progress then exit
BA9B EE 1F 0D INC &0D1F ;else page was crossed last time:
.SA9E
BA9E EE 1E 0D INC &0D1E ;increment run length address
BAA1 AD 12 15 LDA &1512 ;fetch next run length
BAA4 85 A0 STA &A0 ;set run counter
BAA6 68 PLA ;restore A on entry
BAA7 40 RTI ;exit
;unreachable code
BAA8 EA NOP
.SAA9
BAA9 C9 FE CMP #&FE ;is service call number <&FE?
BAAB 90 5C BCC SB09 ;if so then return to process other calls
BAAD D0 1B BNE SACA ;if A=&FF then branch to do main init, else:
BAAF C0 00 CPY #&00 ;Service call &FE = Tube post initialisation
BAB1 F0 56 BEQ SB09 ;ignore call if Y=0 on entry
BAB3 A2 06 LDX #&06 ;else X=6 = fully exploded
BAB5 A9 14 LDA #&14 ;OSBYTE &14 = explode soft character RAM
BAB7 20 F4 FF JSR &FFF4 ;call OSBYTE
.SABA
BABA 2C E0 FE BIT &FEE0 ;print Tube coprocessor banner:
BABD 10 FB BPL SABA ;poll until character in FIFO 0
BABF AD E1 FE LDA &FEE1 ;then read data register 0
BAC2 F0 43 BEQ SB07 ;if =NUL then claim service call and exit
BAC4 20 EE FF JSR &FFEE ;else print the character & loop
BAC7 4C BA BA JMP SABA
.SACA ;Service call &FF = Tube main initialisation
BACA A9 AD LDA #&AD ;EVNTV = &06AD
BACC 8D 20 02 STA &0220
BACF A9 06 LDA #&06
BAD1 8D 21 02 STA &0221
BAD4 A9 16 LDA #&16 ;BRKV = &0016
BAD6 8D 02 02 STA &0202
BAD9 A9 00 LDA #&00
BADB 8D 03 02 STA &0203
BADE A9 8E LDA #&8E ;set Tube status (NAUG p.329)
BAE0 8D E0 FE STA &FEE0 ;enable NMI on R3, IRQ on R1,R4
BAE3 A0 00 LDY #&00 ;initialise offset to 0:
.SAE5
BAE5 B9 4B BB LDA &BB4B,Y ;copy Tube host code from &BB4B..&BE4C
BAE8 99 00 04 STA &0400,Y ;to &0400..&06FF
BAEB B9 4B BC LDA &BC4B,Y ;offset 0 first, then 255..1
BAEE 99 00 05 STA &0500,Y
BAF1 B9 4B BD LDA &BD4B,Y
BAF4 99 00 06 STA &0600,Y
BAF7 88 DEY
BAF8 D0 EB BNE SAE5
BAFA 20 21 04 JSR &0421
BAFD A2 60 LDX #&60 ;initialise offset to &60
.SAFF
BAFF BD 0A BB LDA &BB0A,X ;copy Tube BRK handler from &BB0A..6A
BB02 95 16 STA &16,X ;to &0016..76
BB04 CA DEX
BB05 10 F8 BPL SAFF
.SB07
BB07 A9 00 LDA #&00 ;return A=0 to claim service call
.SB09
BB09 60 RTS
;Tube BRK handler copied to &0016..76
BB0A A9 FF LDA #&FF
BB0C 20 9E 06 JSR &069E
BB0F AD E3 FE LDA &FEE3
BB12 A9 00 LDA #&00
BB14 20 95 06 JSR &0695
BB17 A8 TAY
BB18 B1 FD LDA (&FD),Y
BB1A 20 95 06 JSR &0695
.SB1D
BB1D C8 INY
BB1E B1 FD LDA (&FD),Y
BB20 20 95 06 JSR &0695
BB23 AA TAX
BB24 D0 F7 BNE SB1D
BB26 A2 FF LDX #&FF
BB28 9A TXS
BB29 58 CLI
.SB2A
BB2A 2C E0 FE BIT &FEE0
BB2D 10 06 BPL SB35
.SB2F
BB2F AD E1 FE LDA &FEE1
BB32 20 EE FF JSR &FFEE
.SB35
BB35 2C E2 FE BIT &FEE2
BB38 10 F0 BPL SB2A
BB3A 2C E0 FE BIT &FEE0
BB3D 30 F0 BMI SB2F
BB3F AE E3 FE LDX &FEE3
BB42 86 51 STX &51
BB44 6C 00 05 JMP (&0500)
BB47 EQUB &00
BB48 EQUB &80
BB49 EQUB &00
BB4A EQUB &00
;Tube host code copied to &0400..&06FF
BB4B 4C 84 04 JMP &0484
BB4E 4C A7 06 JMP &06A7
BB51 C9 80 CMP #&80
BB53 90 2B BCC SB80
BB55 C9 C0 CMP #&C0
BB57 B0 1A BCS SB73
BB59 09 40 ORA #&40
BB5B C5 15 CMP &15
BB5D D0 20 BNE SB7F
BB5F 08 PHP
BB60 78 SEI
BB61 A9 05 LDA #&05
BB63 20 9E 06 JSR &069E
BB66 A5 15 LDA &15
BB68 20 9E 06 JSR &069E
BB6B 28 PLP
BB6C A9 80 LDA #&80
BB6E 85 15 STA &15
BB70 85 14 STA &14
BB72 60 RTS
.SB73
BB73 06 14 ASL &14
BB75 B0 06 BCS SB7D
BB77 C5 15 CMP &15
BB79 F0 04 BEQ SB7F
BB7B 18 CLC
BB7C 60 RTS
.SB7D
BB7D 85 15 STA &15
.SB7F
BB7F 60 RTS
.SB80
BB80 08 PHP
BB81 78 SEI
BB82 84 13 STY &13
BB84 86 12 STX &12
BB86 20 9E 06 JSR &069E
BB89 AA TAX
BB8A A0 03 LDY #&03
BB8C A5 15 LDA &15
BB8E 20 9E 06 JSR &069E
.SB91
BB91 B1 12 LDA (&12),Y
BB93 20 9E 06 JSR &069E
BB96 88 DEY
BB97 10 F8 BPL SB91
BB99 A0 18 LDY #&18
BB9B 8C E0 FE STY &FEE0
BB9E BD 18 05 LDA &0518,X
BBA1 8D E0 FE STA &FEE0
BBA4 4A LSR A
BBA5 4A LSR A
BBA6 90 06 BCC SBAE
BBA8 2C E5 FE BIT &FEE5
BBAB 2C E5 FE BIT &FEE5
.SBAE
BBAE 20 9E 06 JSR &069E
.SBB1
BBB1 2C E6 FE BIT &FEE6
BBB4 50 FB BVC SBB1
BBB6 B0 0D BCS SBC5
BBB8 E0 04 CPX #&04
BBBA D0 11 BNE SBCD
.SBBC
BBBC 20 14 04 JSR &0414
BBBF 20 95 06 JSR &0695
BBC2 4C 32 00 JMP &0032
.SBC5
BBC5 4A LSR A
BBC6 90 05 BCC SBCD
BBC8 A0 88 LDY #&88
BBCA 8C E0 FE STY &FEE0
.SBCD
BBCD 28 PLP
BBCE 60 RTS
BBCF 58 CLI
BBD0 B0 11 BCS SBE3
BBD2 D0 03 BNE SBD7
BBD4 4C 9C 05 JMP &059C
.SBD7
BBD7 A2 00 LDX #&00
BBD9 A0 FF LDY #&FF
BBDB A9 FD LDA #&FD
BBDD 20 F4 FF JSR &FFF4
BBE0 8A TXA
BBE1 F0 D9 BEQ SBBC
.SBE3
BBE3 A9 FF LDA #&FF
BBE5 20 06 04 JSR &0406
BBE8 90 F9 BCC SBE3
BBEA 20 D2 04 JSR &04D2
.SBED
BBED A9 07 LDA #&07
BBEF 20 CB 04 JSR &04CB
BBF2 A0 00 LDY #&00
BBF4 84 00 STY &00
.SBF6
BBF6 B1 00 LDA (&00),Y
BBF8 8D E5 FE STA &FEE5
BBFB EA NOP
BBFC EA NOP
BBFD EA NOP
BBFE C8 INY
BBFF D0 F5 BNE SBF6
BC01 E6 54 INC &54
BC03 D0 06 BNE SC0B
BC05 E6 55 INC &55
BC07 D0 02 BNE SC0B
BC09 E6 56 INC &56
.SC0B
BC0B E6 01 INC &01
BC0D 24 01 BIT &01
BC0F 50 DC BVC SBED
BC11 20 D2 04 JSR &04D2
BC14 A9 04 LDA #&04
BC16 A0 00 LDY #&00
BC18 A2 53 LDX #&53
BC1A 4C 06 04 JMP &0406
BC1D A9 80 LDA #&80
BC1F 85 54 STA &54
BC21 85 01 STA &01
BC23 A9 20 LDA #&20
BC25 2D 06 80 AND &8006
BC28 A8 TAY
BC29 84 53 STY &53
BC2B F0 19 BEQ SC46
BC2D AE 07 80 LDX &8007
.SC30
BC30 E8 INX
BC31 BD 00 80 LDA &8000,X
BC34 D0 FA BNE SC30
BC36 BD 01 80 LDA &8001,X
BC39 85 53 STA &53
BC3B BD 02 80 LDA &8002,X
BC3E 85 54 STA &54
BC40 BC 03 80 LDY &8003,X
BC43 BD 04 80 LDA &8004,X
.SC46
BC46 85 56 STA &56
BC48 84 55 STY &55
BC4A 60 RTS
BC4B EQUW &37,&05 ;R2 was &00 - jump osrdch_call
BC4D EQUW &96,&05 ;R2 was &02 - jump oscli_call
BC4F EQUW &F2,&05 ;R2 was &04 - jump short_osbyte
BC51 EQUW &07,&06 ;R2 was &06 - jump long_osbyte
BC53 EQUW &27,&06 ;R2 was &08 - jump osword_call
BC55 EQUW &68,&06 ;R2 was &0A - jump osword0_call
BC57 EQUW &5E,&05 ;R2 was &0C - jump osargs_call
BC59 EQUW &2D,&05 ;R2 was &0E - jump osbget_call
BC5B EQUW &20,&05 ;R2 was &10 - jump osbput_call
BC5D EQUW &42,&05 ;R2 was &12 - jump osfind_call_1
BC5F EQUW &A9,&05 ;R2 was &14 - jump osfile_call
BC61 EQUW &D1,&05 ;R2 was &16 - jump osgbpb_call
BC63 EQUB &86
BC64 EQUB &88
BC65 EQUB &96
BC66 EQUB &98
BC67 EQUB &18
BC68 EQUB &18
BC69 EQUB &82
BC6A EQUB &18
BC6B 20 C5 06 JSR &06C5
BC6E A8 TAY
BC6F 20 C5 06 JSR &06C5
BC72 20 D4 FF JSR &FFD4
BC75 4C 9C 05 JMP &059C
BC78 20 C5 06 JSR &06C5
BC7B A8 TAY
BC7C 20 D7 FF JSR &FFD7
BC7F 4C 3A 05 JMP &053A
BC82 20 E0 FF JSR &FFE0
BC85 6A ROR A
BC86 20 95 06 JSR &0695
BC89 2A ROL A
BC8A 4C 9E 05 JMP &059E
BC8D 20 C5 06 JSR &06C5
BC90 F0 0B BEQ SC9D
BC92 48 PHA
BC93 20 82 05 JSR &0582
BC96 68 PLA
BC97 20 CE FF JSR &FFCE
BC9A 4C 9E 05 JMP &059E
.SC9D
BC9D 20 C5 06 JSR &06C5
BCA0 A8 TAY
BCA1 A9 00 LDA #&00
BCA3 20 CE FF JSR &FFCE
BCA6 4C 9C 05 JMP &059C
BCA9 20 C5 06 JSR &06C5
BCAC A8 TAY
BCAD A2 04 LDX #&04
.SCAF
BCAF 20 C5 06 JSR &06C5
BCB2 95 FF STA &FF,X
BCB4 CA DEX
BCB5 D0 F8 BNE SCAF
BCB7 20 C5 06 JSR &06C5
BCBA 20 DA FF JSR &FFDA
BCBD 20 95 06 JSR &0695
BCC0 A2 03 LDX #&03
.SCC2
BCC2 B5 00 LDA &00,X
BCC4 20 95 06 JSR &0695
BCC7 CA DEX
BCC8 10 F8 BPL SCC2
BCCA 4C 36 00 JMP &0036
BCCD A2 00 LDX #&00
BCCF A0 00 LDY #&00
.SCD1
BCD1 20 C5 06 JSR &06C5
BCD4 99 00 07 STA &0700,Y
BCD7 C8 INY
BCD8 F0 04 BEQ SCDE
BCDA C9 0D CMP #&0D
BCDC D0 F3 BNE SCD1
.SCDE
BCDE A0 07 LDY #&07
BCE0 60 RTS
BCE1 20 82 05 JSR &0582
BCE4 20 F7 FF JSR &FFF7
BCE7 A9 7F LDA #&7F
.SCE9
BCE9 2C E2 FE BIT &FEE2
BCEC 50 FB BVC SCE9
BCEE 8D E3 FE STA &FEE3
.SCF1
BCF1 4C 36 00 JMP &0036
BCF4 A2 10 LDX #&10
.SCF6
BCF6 20 C5 06 JSR &06C5
BCF9 95 01 STA &01,X
BCFB CA DEX
BCFC D0 F8 BNE SCF6
BCFE 20 82 05 JSR &0582
BD01 86 00 STX &00
BD03 84 01 STY &01
BD05 A0 00 LDY #&00
BD07 20 C5 06 JSR &06C5
BD0A 20 DD FF JSR &FFDD
BD0D 20 95 06 JSR &0695
BD10 A2 10 LDX #&10
.SD12
BD12 B5 01 LDA &01,X
BD14 20 95 06 JSR &0695
BD17 CA DEX
BD18 D0 F8 BNE SD12
BD1A F0 D5 BEQ SCF1
BD1C A2 0D LDX #&0D
.SD1E
BD1E 20 C5 06 JSR &06C5
BD21 95 FF STA &FF,X
BD23 CA DEX
BD24 D0 F8 BNE SD1E
BD26 20 C5 06 JSR &06C5
BD29 A0 00 LDY #&00
BD2B 20 D1 FF JSR &FFD1
BD2E 48 PHA
BD2F A2 0C LDX #&0C
.SD31
BD31 B5 00 LDA &00,X
BD33 20 95 06 JSR &0695
BD36 CA DEX
BD37 10 F8 BPL SD31
BD39 68 PLA
BD3A 4C 3A 05 JMP &053A
BD3D 20 C5 06 JSR &06C5
BD40 AA TAX
BD41 20 C5 06 JSR &06C5
BD44 20 F4 FF JSR &FFF4
.SD47
BD47 2C E2 FE BIT &FEE2
BD4A 50 FB BVC SD47
BD4C 8E E3 FE STX &FEE3
.SD4F
BD4F 4C 36 00 JMP &0036
BD52 20 C5 06 JSR &06C5
BD55 AA TAX
BD56 20 C5 06 JSR &06C5
BD59 A8 TAY
BD5A 20 C5 06 JSR &06C5
BD5D 20 F4 FF JSR &FFF4
BD60 49 9D EOR #&9D
BD62 F0 EB BEQ SD4F
BD64 6A ROR A
BD65 20 95 06 JSR &0695
.SD68
BD68 2C E2 FE BIT &FEE2
BD6B 50 FB BVC SD68
BD6D 8C E3 FE STY &FEE3
BD70 70 D5 BVS SD47
BD72 20 C5 06 JSR &06C5
BD75 A8 TAY
.SD76
BD76 2C E2 FE BIT &FEE2
BD79 10 FB BPL SD76
BD7B AE E3 FE LDX &FEE3
BD7E CA DEX
BD7F 30 0F BMI SD90
.SD81
BD81 2C E2 FE BIT &FEE2
BD84 10 FB BPL SD81
BD86 AD E3 FE LDA &FEE3
BD89 9D 28 01 STA &0128,X
BD8C CA DEX
BD8D 10 F2 BPL SD81
BD8F 98 TYA
.SD90
BD90 A2 28 LDX #&28
BD92 A0 01 LDY #&01
BD94 20 F1 FF JSR &FFF1
.SD97
BD97 2C E2 FE BIT &FEE2
BD9A 10 FB BPL SD97
BD9C AE E3 FE LDX &FEE3
BD9F CA DEX
BDA0 30 0E BMI SDB0
.SDA2
BDA2 BC 28 01 LDY &0128,X
.SDA5
BDA5 2C E2 FE BIT &FEE2
BDA8 50 FB BVC SDA5
BDAA 8C E3 FE STY &FEE3
BDAD CA DEX
BDAE 10 F2 BPL SDA2
.SDB0
BDB0 4C 36 00 JMP &0036
BDB3 A2 04 LDX #&04
.SDB5
BDB5 20 C5 06 JSR &06C5
BDB8 95 00 STA &00,X
BDBA CA DEX
BDBB 10 F8 BPL SDB5
BDBD E8 INX
BDBE A0 00 LDY #&00
BDC0 8A TXA
BDC1 20 F1 FF JSR &FFF1
BDC4 90 05 BCC SDCB
BDC6 A9 FF LDA #&FF
BDC8 4C 9E 05 JMP &059E
.SDCB
BDCB A2 00 LDX #&00
BDCD A9 7F LDA #&7F
BDCF 20 95 06 JSR &0695
.SDD2
BDD2 BD 00 07 LDA &0700,X
BDD5 20 95 06 JSR &0695
BDD8 E8 INX
BDD9 C9 0D CMP #&0D
BDDB D0 F5 BNE SDD2
BDDD 4C 36 00 JMP &0036
.SDE0
BDE0 2C E2 FE BIT &FEE2
BDE3 50 FB BVC SDE0
BDE5 8D E3 FE STA &FEE3
BDE8 60 RTS
.SDE9
BDE9 2C E6 FE BIT &FEE6
BDEC 50 FB BVC SDE9
BDEE 8D E7 FE STA &FEE7
BDF1 60 RTS
BDF2 A5 FF LDA &FF
BDF4 38 SEC
BDF5 6A ROR A
BDF6 30 0F BMI SE07
BDF8 48 PHA
BDF9 A9 00 LDA #&00
BDFB 20 BC 06 JSR &06BC
BDFE 98 TYA
BDFF 20 BC 06 JSR &06BC
BE02 8A TXA
BE03 20 BC 06 JSR &06BC
BE06 68 PLA
.SE07
BE07 2C E0 FE BIT &FEE0
BE0A 50 FB BVC SE07
BE0C 8D E1 FE STA &FEE1
BE0F 60 RTS
.SE10
BE10 2C E2 FE BIT &FEE2
BE13 10 FB BPL SE10
BE15 AD E3 FE LDA &FEE3
BE18 60 RTS
.SE19
BE19 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
BE1C EQUB &83 ;yellow alphanumerics
BE1D EQUB &8D ;double height
BE1E EQUS " C O P Y R I G H T N O T I C E"
BE3E EQUB &0D
BE3F EQUB &0A
BE40 EQUB &FF
BE41 60 RTS
;*COPYRIGHT
BE42 20 74 AD JSR RD74 ;set display MODE 7
BE45 20 67 84 JSR P467 ;print newline
BE48 20 19 BE JSR SE19
BE4B 20 19 BE JSR SE19
BE4E 20 D2 A3 JSR R3D2 ;print VDU sequence immediate
BE51 EQUB &0D
BE52 EQUB &0A
BE53 EQUB &0A
BE54 EQUS "This Double Density Operating System"
BE78 EQUB &0D
BE79 EQUB &0A
BE7A EQUS "was developed for the BBC computer by"
BE9F EQUB &0D
BEA0 EQUB &0A
BEA1 EQUB &83 ;yellow alphanumerics
BEA2 EQUS "SLOGGER SOFTWARE and OPUS SUPPLIES"
BEC4 EQUB &0D
BEC5 EQUB &0A
BEC6 EQUS "Any unauthorised copying of this"
BEE6 EQUB &0D
BEE7 EQUB &0A
BEE8 EQUS "product is unlawful and may result in"
BF0D EQUB &0D
BF0E EQUB &0A
BF0F EQUS "Slogger or Opus taking appropriate"
BF31 EQUB &0D
BF32 EQUB &0A
BF33 EQUS "action."
BF3A EQUB &0D
BF3B EQUB &0A
BF3C EQUB &0A
BF3D EQUB &FF
BF3E 60 RTS
# if defined _DDOS356
BF3F EQUB &FF
BF40 EQUB &05,&06,&15,&16
BF44 EQUB &FF,&FF,&FF,&FF
.SF48
BF48 AA TAX
BF49 BD 40 BF LDA &BF40,X ;get flags for drive 0..3 in X
BF4C 85 F9 STA &F9 ;store in temporary location
BF4E AD E3 10 LDA &10E3 ;get density flag
BF51 29 40 AND #&40 ;extract bit 6 (1 = double density)
BF53 4A LSR A ;move to bit 5
BF54 49 20 EOR #&20 ;invert for Master (0 = double density)
BF56 05 F9 ORA &F9 ;add drive flags (only Compact uses &F8,9)
BF58 60 RTS
# elif defined _DDOS357
.SF40
BF40 AA TAX ;put drive number in X
BF41 AD E3 10 LDA &10E3 ;get density flag
BF44 29 40 AND #&40 ;extract bit 6 (1 = double density)
BF46 4A LSR A ;move to bit 5
BF47 5D 8B A5 EOR &A58B,X ;apply flags for drive 0..3 in X
BF4A 60 RTS ;return control latch value in A
.SF4B
BF4B D0 0A BNE SF57
BF4D C0 04 CPY #&04 ;Service call &12 = initialise FS
BF4F D0 06 BNE SF57 ;if number of FS to initialise = 4
BF51 20 00 A3 JSR R300 ;then save AXY
BF54 4C 0F 82 JMP P20F ;and initialise DDOS
.SF57
BF57 4C 0D 81 JMP P10D ;serve calls &8,A and pass other calls
;OSFSC
BFE8 C9 0A CMP #&0A
BFEA D0 0E BNE SFFA
BFEC 20 00 A3 JSR R300 ;OSFSC &0A = *INFO. save AXY
BFEF 20 42 8F JSR PF42 ;set GSINIT pointer to XY, set Y=0
BFF2 20 24 8F JSR PF24 ;set up trampoline to read *INFO entry
BFF5 A0 00 LDY #&00 ;set Y = 0 offset for GSINIT
BFF7 4C 51 89 JMP P951 ;jump into *INFO
.SFFA
BFFA 4C 68 94 JMP Q468 ;serve other OSFSC calls
# endif /* _DDOS356 */
BFFF EQUB &00 ;make 16 KiB ROM image
# endif /* _DDOS346 */
#endif /* _DDOS316 */
#if defined _DFSFIX
.SF62 ;call OSFILE 1 = write catalogue information:
BF62 A2 01 LDX #&01
.SF64 ;Handle OSFILE calls 7,9,11 or validate index
BF64 E8 INX ;enter with X = A, convert X to table offset
BF65 E0 0A CPX #&0A ;is it OSFILE 9 = set filetype/stamp?
BF67 F0 F9 BEQ SF62 ;then use OSFILE 1 = write catalogue info
BF69 E0 0C CPX #&0C ;is it OSFILE call 11 = create file w/ stamp?
BF6B F0 04 BEQ SF71 ;if so then create file
BF6D E0 08 CPX #&08 ;else is it OSFILE 7 = create file? if not
BF6F D0 0A BNE SF7B ;return X = offset, C=0 iff call known, else:
.SF71 ;OSFILE 7 = create file
BF71 20 F0 90 JSR Q0F0 ;create file from OSFILE block
BF74 20 22 9C JSR QC22 ;set up pointer to user's OSFILE block
BF77 20 06 8A JSR PA06 ;return catalogue information to OSFILE block
BF7A 38 SEC ;set C=1, return on exit
.SF7B
BF7B 60 RTS
.SF7C
BF7C 68 PLA ;extend file. restore file handle
BF7D A8 TAY
BF7E 20 06 98 JSR Q806 ;set PTR = request, to extend file
BF81 A9 80 LDA #&80 ;a=&80 so that c=1 to restore original PTR:
.SF83 ;OSARGS A=1/3, Y>0 set PTR/EXT
BF83 F0 36 BEQ SFBB ;if call number = 1, set PTR, else:
BF85 0A ASL A ;OSARGS 3,Y. c=0 read PTR to restore later:
.SF86
BF86 8A TXA ;save OSARGS pointer
BF87 48 PHA
BF88 A2 B6 LDX #&B6 ;point X to PTR store used by OSGBPB
BF8A A9 00 LDA #&00 ;set A=0, Z=1 to read/set PTR not EXT!
BF8C 20 A4 97 JSR Q7A4 ;read temporary PTR if C=0 or set PTR if C=1
BF8F 68 PLA ;restore user's OSARGS pointer
BF90 AA TAX
BF91 98 TYA ;save file handle
BF92 48 PHA
BF93 20 C1 BF JSR SFC1 ;clear EOF warning flag
BF96 20 CC 9A JSR QACC ;compare EXT - request
BF99 90 E1 BCC SF7C ;if EXT < request then extend file
BF9B B9 0C 11 LDA &110C,Y ;else get channel read-only bit in b7
BF9E 19 0E 11 ORA &110E,Y ;or with channel file locked bit in b7
BFA1 30 05 BMI SFA8 ;if either is set do not write new EXT to cat
BFA3 A9 20 LDA #&20 ;else b5=1 EXT changed
BFA5 20 3F 99 JSR Q93F ;set channel flag bits (A = OR mask)
.SFA8
BFA8 20 76 A4 JSR R476 ;truncate file. add 4 to Y
BFAB 20 53 98 JSR Q853 ;copy request to EXT
BFAE 68 PLA ;restore file handle
BFAF A8 TAY
BFB0 8A TXA ;save OSARGS pointer
BFB1 48 PHA
BFB2 98 TYA ;copy file handle to X
BFB3 AA TAX
BFB4 20 B6 94 JSR Q4B6 ;compare PTR - EXT
BFB7 68 PLA ;restore OSARGS pointer
BFB8 AA TAX
BFB9 90 C0 BCC SF7B ;if PTR < EXT then return, else:
.SFBB ;OSARGS A=1, Y>0
BFBB 20 06 98 JSR Q806 ;set PTR = request
BFBE 20 00 A3 JSR R300 ;save AXY again
.SFC1
BFC1 20 A7 98 JSR Q8A7 ;ensure file handle valid and open
BFC4 A9 EF LDA #&EF ;b4=0 EOF warning flag clear
BFC6 4C 46 99 JMP Q946 ;clear channel flag bits
.SFC9 ;Clear EOF warning flag in OSGBPB
BFC9 AC 60 10 LDY &1060 ;set Y = file handle from OSGBPB block
BFCC 20 C1 BF JSR SFC1 ;clear EOF warning flag
BFCF 4C 0A 9E JMP QE0A ;set up pointer to user's OSGBPB block
;OSFIND
BFD2 48 PHA ;save call number
BFD3 29 48 AND #&48 ;test b6=read access, b3=error if not found
BFD5 C9 48 CMP #&48 ;set carry flag iff b6, b3 both set
BFD7 68 PLA ;restore call number
BFD8 08 PHP ;save carry flag
BFD9 29 C0 AND #&C0 ;pass only b7=write access, b6 to DDOS
BFDB 20 C1 95 JSR Q5C1 ;call DDOS routine
BFDE 28 PLP ;restore carry flag
BFDF 49 00 EOR #&00 ;test if file handle in A is non-zero
BFE1 90 98 BCC SF7B ;if no error is required then return
BFE3 D0 96 BNE SF7B ;if a file was opened then return
BFE5 4C 43 89 JMP P943 ;else raise "File not found" error.
#endif /* _DFSFIX */
;Code fragments with no known references:
;871A..50 = &37 = 55 bytes
;8F22..27 = &06 = 6 bytes used by DDOS 3.57
;92C6..CD = &08 = 8 bytes
;92F6..FF = &0A = 10 bytes used by seek NMI fix
;A46C = &01 = 1 byte
;A509..10 = &08 = 8 bytes used by RAM disc fix
;A56D..73 = &07 = 7 bytes used by BeebEm fix
;A57D..7F = &03 = 3 bytes
;A58F..96 = &08 = 8 bytes (vacated by RAM disc fix)
;A58A..8E = &05 = 5 bytes used by DDOS 3.57
;A701 = &01 = 1 byte
;BA?? = &01 = 1 byte
;Total = &69 = 105 bytes
;Variables
;00A6..A7 User data address during transfer
;00A9 b7=Copying between different discs in same drive
;00AA &00=Source disc in drive &80=Destination disc in drive
;00B3 Pointer to file entry in catalogue, 0..&F0, multiple of 8
;00BA Logical track number of disc operation
;00BB Starting sector number of disc operation
;00BC..BD Pointer to filename in OSFILE
;00BE..C5 Low words of load, exec, start, end addresses in OSFILE
;00C3 (1, copied to &A4, then &A1, causes file buffer transfers to =256)
;00C7..CD Current filename
;00CE Current directory
;00CF b3..0=current drive b6..4=current volume
;0DF0,X High byte of address of private page (X=?&F4)
;1000 Data transfer call number 0=read data 1=write data
; 3=write deleted data 4=verify data
;1001 *SROM number of paged ROM slot to page in during disc operations
;100E..0F Number of sectors on surface of double density disc (from disc cat)
;1060..6C OSGBPB block
;106F..76 High words of load, exec, start, end addresses in OSFILE
;1083 &00=transferring to/from host &FF=transferring to/from Tube
;1084 Drive and volume of catalogue in pages &E..F; &FF=catalogue invalid
;1087 NMI ownership flag b7=we own NMI
;108B Number of pages of available user memory
;108C..8D Physical track number under heads on drive 0/2, 1/3
;10C0 Private page +&C0: b7=1 iff private page initialised
;10C1 Private page +&C1: b7=1 iff we own the shared workspace
;10C2 First shared workspace sentinel &41=workspace valid
;10C3 Channel open flags
;10CA Default (CSD) directory character
;10CB Default (CSD) drive (b3..0) and volume (b6..4)
;10CC Library directory character
;10CD Library drive (b3..0) and volume (b6..4)
;10CE Cleared at &82B7, otherwise unused
;10CF Pointer to file entry in catalogue
;10CF Y position of cursor
;10D0 &23=wildcard characters allowed in filename &FF=no wildcards
;10D1 *OPT 1 monitor 0=verbose &FF=quiet
;10D2 *ENABLE counter 1=*ENABLE just called 0=current command enabled
; &FF=current command not enabled
;10D3 Source volume in *BACKUP, *COPY
;10D4 Destination volume in *BACKUP, *COPY
;10D5 b7=Tube data transfer
;10D7 b7..4=boot option of source volume in *BACKUP, *MCOPY
;10D7..D8 Action address in OSGBPB
;10D9..DA Pointer to arguments of *RUN, */ command
;10DD <&80 "print" to error message >=&80 print to screen
; (if <&80, offset of next error character in page &01)
;10DE Second shared workspace sentinel &48=workspace valid
;10E0..3 Special registers 0..3
;10E0 &00=single stepping b6=double stepping b7=automatic stepping
;10E1 Number of sectors per track &0A=single density &12=double density
;10E2 First track of current volume (=0 unless set from disc catalogue)
;10E3 &00=single density b6=double density b7=automatic density
;10E6..B,Y Drive parameters for channel (6 bytes per channel, Y=6*n, n=0..6)
; n=0..4 for channel &11..15 n=5 source drive n=6 destination drive
; 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
;10E0 sC pC vC dC .. .. s1 p1 v1 d1 .. .. s2 p2 v2 d2
;10F0 .. .. s3 p3 v3 d3 .. .. s4 p4 v4 d4 .. .. s5 p5
;1100 v5 d5 .. .. sS pS vS dS .. .. sD pD vD dD .. ..
;1100..C,Y Name of open file (even addresses)
;1101..F,Y Load/exec/length/start sector in catalogue format (odds)
;110C,Y Seventh character of open filename; b7=read-only channel
;110E,Y Directory of open filename; b7=file locked
;1110..2,Y PTR file pointer
;1114..6,Y EXT file length
;1117,Y Channel flags b7=buffer contains byte at PTR
; b6=buffer changed b5=EXT changed (not cleared on ensure)
; b4=EOF warning given
;1118,Y Always 0 (&1118..A,Y = length in bytes, rounded up)
;1119..A,Y Length of file in sectors, according to catalogue
;111B,Y Bit mask corresponding to channel in flag byte &10C3
;111C..D,Y LBA of sector buffer relative to start of volume data area
;Errata
;OSFILE does not load or save files 64 KiB or larger to the RAM disc
;correctly.
;BeebEm 4.14 does not tolerate the WD 1770 Write Sector command being
;terminated during the NMI service routine; the last byte is dropped.
;(disc1770.cpp:326)
;This Perl script recreates the binary from this listing.
;Copy the text between the cut lines.
;Paste it into a new file, asm2bin.pl, and remove the column of ;
;Then call it with
; perl asm2bin.pl -D_DDOS346PRE -b 8000 -o ddos346pre ddos.asm.txt
; perl asm2bin.pl -D_DDOS316 -b 8000 -o ddos316 ddos.asm.txt
; perl asm2bin.pl -D_DDOS336 -b 8000 -o ddos336 ddos.asm.txt
; perl asm2bin.pl -D_DDOS346 -b 8000 -o ddos346 ddos.asm.txt
; perl asm2bin.pl -D_DDOS356 -b 8000 -o ddos356 ddos.asm.txt
; perl asm2bin.pl -D_DDOS357 -b 8000 -o ddos357 ddos.asm.txt
;-------->8---
;#!/usr/bin/perl
;
;#Usage: perl asm2bin.pl
;# {-D SYMBOL[=VALUE]} [-E|-d] [-b BASE]
;# -o OUTFILE [FILE...]
;
;use Getopt::Std;
;use IO::Seekable qw(SEEK_SET SEEK_CUR SEEK_END);
;
;@x=(2); $t[6]=2; $t[7]=4;
;
;for($i=0;$i<@ARGV && ($arg = $ARGV[$i]) ne '--'; ++$i) {
; if(substr($arg,0,2) eq '-D') {
; if(($dfn=substr($arg,2)) eq '') {
; $dfn = $ARGV[++$i];
; }
; if(($x=index($dfn,'=')) > 0) {
; $symbol{substr($dfn,0,$x)} = substr($dfn,$x+1);
; } elsif($dfn ne '') {
; $symbol{$dfn} = 1;
; }
; }
;}
;
;getopts("D:Eb:do:");
;die "No output file specified" if $opt_o eq '';
;$opt_b = hex($opt_b);
;
;open(BIN,"+>$opt_o") or die;
;binmode(BIN) unless $opt_E;
;while(<>) {
; y/\n\r//d;
; if(substr($_,0,1) ne '#') {
; while(($key, $value) = each %symbol) {
; $x=0;
; while(($x = index($_,$key,$x)) >= 0) {
; substr($_,$x,length($key),$value);
; $x+=length($value);
; }
; }
; }
; if(/^#\s*()ifdef\s+(\S*)$/
; || /^#\s*((?:el)?)if\s+defined\s*\(\s*(\S*)\s*\)/
; || /^#\s*((?:el)?)if\s+defined\s*(\S*)/) {
; unshift@x,4 if$1 eq'';
; $x[0]=$t[$x[0]|$x[1]&2|!exists($symbol{$2})];$_='';
; }elsif(/^#\s*()ifndef\s+(\S*)$/
; || /^#\s*((?:el)?)if\s+\!\s*defined\s*\(\s*(\S*)\s*\)/
; || /^#\s*((?:el)?)if\s+\!\s*defined\s*(\S*)/) {
; unshift@x,4 if$1 eq'';
; $x[0]=$t[$x[0]|$x[1]&2|exists($symbol{$2})];$_='';
; }elsif(/^#\s*((?:el)?)if\s+\!\s*(\S*)\s*$/) {
; unshift@x,4 if$1 eq'';
; $x[0]=$t[$x[0]|$x[1]&2|($2 !=0)];$_='';
; }elsif(/^#\s*((?:el)?)if\s+(\S*)\s*$/) {
; unshift@x,4 if$1 eq'';
; $x[0]=$t[$x[0]|$x[1]&2|($2 ==0)];$_='';
; }elsif(/^#\s*else(?!\S)/) {
; $x[0]=$t[$x[0]|$x[1]&2];$_='';
; }elsif(/^#\s*endif(?!\S)/) {
; shift@x;@x=(2)unless@x;$_='';
; }elsif($x[0] & 2 && /^#\s*define\s+(\S+)\s*(.*)$/) {
; $symbol{$1}=$2;$_='';
; }elsif($x[0] & 2 && /^#\s*undef\s+(\S+)/) {
; delete $symbol{$1};$_='';
; }
; if($opt_E) {
; print BIN ($x[0] & 2 ? $_ : ''), "\n"; next;
; }elsif(($x[0] & 2)==0) {
; next;
; }
; if(/^ {0,2}([0-9A-F]{4})/) {
; print STDERR "seek $1\n" if $opt_d;
; seek(BIN,hex($1)-$opt_b,SEEK_SET);
; }
; if(/^ {0,2}[^;\\]{4}((?: {0,2}[0-9A-F]{2}){1,3})/) {
; ($a=$1)=~y/ //d;
; print STDERR " write $a\n" if $opt_d;
; print BIN pack("H*",$a);
; }
; if(/^ {0,2}[^;\\]{4} {0,2}EQUS ((?:"[^"]*")*)/) {
; ($a=substr($1,1,length($1)-2))=~s/""/"/g;
; print STDERR " write $a\n" if $opt_d;
; print BIN $a;
; }
; if(/^ {0,2}[^;\\]{4} {0,2}EQU[^S] (&[0-9A-F]{2}(?:,&[0-9A-F]{2})*)/){
; ($a=$1)=~y/,&//d;
; print STDERR " write $a\n" if $opt_d;
; print BIN pack("H*",$a);
; }
;}
;close(BIN);
;-------->8---
;End of ddos.asm.txt