From 7b6be0827dd47e11faccfe59b9c9d814817735e1 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 27 Jan 2018 17:17:15 +0000 Subject: [PATCH] DiskII formatter: add reference material for ProDOS formatter routine (#125) --- .../Format1.1.1-annotated.txt | 806 +++++++++ docs/DiskII Formatter/Formatter.dsk | Bin 0 -> 143360 bytes .../apple3_SRC_Disk_Formatter.pdf | Bin 0 -> 69202 bytes docs/DiskII Formatter/formatter.s | 1494 +++++++++++++++++ 4 files changed, 2300 insertions(+) create mode 100644 docs/DiskII Formatter/Format1.1.1-annotated.txt create mode 100644 docs/DiskII Formatter/Formatter.dsk create mode 100644 docs/DiskII Formatter/apple3_SRC_Disk_Formatter.pdf create mode 100644 docs/DiskII Formatter/formatter.s diff --git a/docs/DiskII Formatter/Format1.1.1-annotated.txt b/docs/DiskII Formatter/Format1.1.1-annotated.txt new file mode 100644 index 00000000..9eb6d602 --- /dev/null +++ b/docs/DiskII Formatter/Format1.1.1-annotated.txt @@ -0,0 +1,806 @@ +;* +;* +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * +;* * * * +;* * M U S T B E O N P A G E B O U N D A R Y * * +;* * * * +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * +;* * +;* ProDOS DISK ][ Formatter Device Driver * +;* * +;* Copyright Apple Computer, Inc., 1982-1984 * +;* * +;* Enter with ProDOS device number in A-register: * +;* Zero = bits 0, 1, 2, 3 * +;* Slot No.= bits 4, 5, 6 * +;* Drive 1 = bit 7 off * +;* Drive 2 = bit 7 on * +;* * +;* Error codes returned in A-register: * +;* $00 : Good completion * +;* $27 : Unable to format * +;* $2B : Write-Protected * +;* $33 : Drive too SLOW * +;* $34 : Drive too FAST * +;* NOTE: Carry flag is set if error occured. * +;* * +;* Uses zero page locations $D0 thru $DD * +;* * +;* - - - - - - - - - - - - - - - - - - - - - - - - - - * +;* Modified 15 December 1983 to disable interrupts * +;* Modified 20 December 1983 to increase tolerance * +;* of disk speed check * +;* Modified 30 March 1983 to increase tolerance of * +;* disk speed * +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * + +; +; Disassembly and annotations by TC (Nov. 2017) +; . disassembly from prodos_utility.dsk (ProDOS 1.1.1) +; + +; +; Entrypoint +; Pre: A=slot*16, ($DE)=#$01=volume# +; +7900- 08 PHP +7901- 78 SEI ; interrupt disable +7902- 20 3A 79 JSR $793A +7905- 28 PLP ; restore interrupt ena/dis state +7906- C9 00 CMP #$00 +7908- D0 02 BNE $790C +790A- 18 CLC ; res=OK +790B- 60 RTS + +; error: +790C- C9 02 CMP #$02 +790E- D0 05 BNE $7915 +7910- A9 2B LDA #$2B ; MLI error: write protected +7912- 4C 21 79 JMP $7921 +; +7915- C9 01 CMP #$01 +7917- D0 05 BNE $791E +7919- A9 27 LDA #$27 ; MLI error: I/O error +791B- 4C 21 79 JMP $7921 +; +791E- 18 CLC +791F- 69 30 ADC #$30 ; =>$33 or $34 +7921- 38 SEC ; res=ERROR +7922- 60 RTS +; end + +; Seek to track +; Pre: A=trk#, X=slot*16 +7923- 0A ASL ; A=half track +7924- 0E 24 7D ASL $7D24 +7927- 8D 36 7D STA $7D36 +792A- 8A TXA +792B- 4A LSR +792C- 4A LSR +792D- 4A LSR +792E- 4A LSR ; A=slot +792F- A8 TAY ; Y=slot +7930- AD 36 7D LDA $7D36 +7933- 20 C6 7A JSR $7AC6 +7936- 4E 24 7D LSR $7D24 +7939- 60 RTS +; ??? (end) + +; FormatDisk (called from Entrypoint) +; Pre: A=slot*16, A.b7=drive# +793A- AA TAX +793B- 29 70 AND #$70 +793D- 8D 23 7D STA $7D23 ; set slot*16 +7940- 8A TXA +7941- AE 23 7D LDX $7D23 +7944- 2A ROL ; C=drive# +7945- A9 00 LDA #$00 +7947- 2A ROL +7948- D0 06 BNE $7950 +794A- BD 8A C0 LDA $C08A,X ; select drive-1 +794D- 4C 53 79 JMP $7953 +7950- BD 8B C0 LDA $C08B,X ; select drive-2 +; +7953- BD 89 C0 LDA $C089,X ; motor on +7956- A9 D7 LDA #$D7 +7958- 85 DA STA $DA ; ($DA) = #$D7 +795A- A9 50 LDA #$50 +795C- 8D 24 7D STA $7D24 ; ($7D24) = 80 + +; Seek to track 0 +795F- A9 00 LDA #$00 +7961- 20 23 79 JSR $7923 + +; Wait (until motor up to speed?) +7964- A5 DA LDA $DA ; read_vol +7966- F0 06 BEQ $796E +7968- 20 3A 7C JSR $7C3A ; Wait incs read_vol +796B- 4C 64 79 JMP $7964 + +; Init vars/consts +796E- A5 DE LDA $DE +7970- 85 D3 STA $D3 ; ($D3) = write_vol = 1 (constant) +7972- A9 AA LDA #$AA +7974- 85 D0 STA $D0 ; ($D0) = #$AA (constant) +7976- AD 20 7D LDA $7D20 ; max_gap3 +7979- 18 CLC +797A- 69 02 ADC #$02 +797C- 85 D4 STA $D4 ; ($D4) = max_gap3 + 2 +797E- A9 00 LDA #$00 +7980- 85 D1 STA $D1 ; ($D1) = write_trk = 0 + +; Write next track +7982- A5 D1 LDA $D1 +7984- AE 23 7D LDX $7D23 +7987- 20 23 79 JSR $7923 +798A- AE 23 7D LDX $7D23 +798D- BD 8D C0 LDA $C08D,X ; load disk write prot to latch(b7=1 => write protected) +7990- BD 8E C0 LDA $C08E,X ; set read mode & read latch +7993- A8 TAY +7994- BD 8E C0 LDA $C08E,X ; set read mode +7997- BD 8C C0 LDA $C08C,X ; read nib to latch & read latch +799A- 98 TYA +799B- 10 05 BPL $79A2 +799D- A9 02 LDA #$02 ; Error = write protected +799F- 4C F9 79 JMP $79F9 + +; Write track +79A2- 20 63 7C JSR $7C63 +79A5- 90 0E BCC $79B5 +; Error... +79A7- A9 01 LDA #$01 +79A9- A4 D4 LDY $D4 +79AB- CC 1F 7D CPY $7D1F +79AE- B0 02 BCS $79B2 +79B0- A9 04 LDA #$04 +79B2- 4C F9 79 JMP $79F9 ; error code = 4 (Drive too FAST) + +; Succeeded writing track, now check gap3_count tolerance +79B5- A4 D4 LDY $D4 +79B7- CC 1F 7D CPY $7D1F +79BA- B0 05 BCS $79C1 +79BC- A9 04 LDA #$04 +79BE- 4C F9 79 JMP $79F9 ; error code = 4 (Drive too FAST) +; +79C1- CC 20 7D CPY $7D20 +79C4- 90 05 BCC $79CB +79C6- A9 03 LDA #$03 +79C8- 4C F9 79 JMP $79F9 ; error code = 3 (Drive too SLOW) + +; Read a max of 15 (not 16) address fields, looking for sector 0 +79CB- AD 22 7D LDA $7D22 ; A = #$10 (constant) +79CE- 8D 25 7D STA $7D25 +; +79D1- CE 25 7D DEC $7D25 +79D4- D0 05 BNE $79DB +79D6- A9 01 LDA #$01 +79D8- 4C F9 79 JMP $79F9 ; error code = 1 (I/O error) +79DB- AE 23 7D LDX $7D23 +79DE- 20 6A 7A JSR $7A6A ; Read address field +79E1- B0 EE BCS $79D1 +79E3- A5 D8 LDA $D8 ; sector 0? +79E5- D0 EA BNE $79D1 ; ... no, so keep reading + +; Got address field for sector 0: + +; Verify sector +79E7- AE 23 7D LDX $7D23 +79EA- 20 07 7A JSR $7A07 ; ??? +79ED- B0 E2 BCS $79D1 + +; Prep for formatting next track +79EF- E6 D1 INC $D1 ; inc write_trk +79F1- A5 D1 LDA $D1 +79F3- C9 23 CMP #$23 ; done 35 tracks? +79F5- 90 8B BCC $7982 ; ... no, so write next track +79F7- A9 00 LDA #$00 ; res = OK + +79F9- 48 PHA ; push error code +79FA- AE 23 7D LDX $7D23 +79FD- BD 88 C0 LDA $C088,X +7A00- A9 00 LDA #$00 +7A02- 20 23 79 JSR $7923 +7A05- 68 PLA ; pop error code +7A06- 60 RTS +; end + +; +; Verify sector +; + +; Read data prologue (D5 AA AD) within 32 nibbles +7A07- A0 20 LDY #$20 +7A09- 88 DEY +7A0A- F0 5C BEQ $7A68 +7A0C- BD 8C C0 LDA $C08C,X +7A0F- 10 FB BPL $7A0C +7A11- 49 D5 EOR #$D5 +7A13- D0 F4 BNE $7A09 +7A15- EA NOP +7A16- BD 8C C0 LDA $C08C,X +7A19- 10 FB BPL $7A16 +7A1B- C9 AA CMP #$AA +7A1D- D0 F2 BNE $7A11 +7A1F- A0 56 LDY #$56 ; Y=#$56 +7A21- BD 8C C0 LDA $C08C,X +7A24- 10 FB BPL $7A21 +7A26- C9 AD CMP #$AD +7A28- D0 E7 BNE $7A11 +; Read data +7A2A- A9 00 LDA #$00 ; ($D5) = #$FF = Number of #$96 nibbles to read +7A2C- 88 DEY +7A2D- 84 D5 STY $D5 +7A2F- BD 8C C0 LDA $C08C,X +7A32- 10 FB BPL $7A2F +7A34- C9 96 CMP #$96 +7A36- D0 30 BNE $7A68 +7A38- A4 D5 LDY $D5 +7A3A- D0 F0 BNE $7A2C +; +7A3C- 84 D5 STY $D5 +7A3E- BD 8C C0 LDA $C08C,X +7A41- 10 FB BPL $7A3E +7A43- C9 96 CMP #$96 +7A45- D0 21 BNE $7A68 +7A47- A4 D5 LDY $D5 +7A49- C8 INY +7A4A- D0 F0 BNE $7A3C +; +7A4C- BD 8C C0 LDA $C08C,X +7A4F- 10 FB BPL $7A4C +7A51- C9 96 CMP #$96 +7A53- D0 13 BNE $7A68 +; Read data epilogue (DE AA) +7A55- BD 8C C0 LDA $C08C,X +7A58- 10 FB BPL $7A55 +7A5A- C9 DE CMP #$DE +7A5C- D0 0A BNE $7A68 ; error +7A5E- EA NOP +7A5F- BD 8C C0 LDA $C08C,X +7A62- 10 FB BPL $7A5F +7A64- C9 AA CMP #$AA +7A66- F0 5C BEQ $7AC4 ; CLC & RTS +7A68- 38 SEC ; error +7A69- 60 RTS +; end + +; +; Read address field +; +; Post: +; ($D7) = Chksum +; ($D8) = Sec +; ($D9) = Trk +; ($DA) = Vol +; +; Carry set => error: +; . max nibble count read before addr prologue +; . chksum error +; . addr epilogue not correct +; + +; Init: nibble count until error: 3+3*256 = 3+768 = 771 +7A6A- A0 FC LDY #$FC +7A6C- 84 DC STY $DC + +; Read until address prologue (D5 AA 96) +7A6E- C8 INY +7A6F- D0 04 BNE $7A75 +7A71- E6 DC INC $DC +7A73- F0 F3 BEQ $7A68 ; error +7A75- BD 8C C0 LDA $C08C,X +7A78- 10 FB BPL $7A75 +7A7A- C9 D5 CMP #$D5 +7A7C- D0 F0 BNE $7A6E +7A7E- EA NOP +7A7F- BD 8C C0 LDA $C08C,X +7A82- 10 FB BPL $7A7F +7A84- C9 AA CMP #$AA +7A86- D0 F2 BNE $7A7A +7A88- A0 03 LDY #$03 ; Y=3 +7A8A- BD 8C C0 LDA $C08C,X +7A8D- 10 FB BPL $7A8A +7A8F- C9 96 CMP #$96 +7A91- D0 E7 BNE $7A7A + +; Read 4&4 +; ($D7) = Chksum +; ($D8) = Sec +; ($D9) = Trk +; ($DA) = Vol +7A93- A9 00 LDA #$00 +7A95- 85 DB STA $DB ; update chksum +7A97- BD 8C C0 LDA $C08C,X +7A9A- 10 FB BPL $7A97 +7A9C- 2A ROL +7A9D- 85 DD STA $DD +7A9F- BD 8C C0 LDA $C08C,X +7AA2- 10 FB BPL $7A9F +7AA4- 25 DD AND $DD +7AA6- 99 D7 00 STA $00D7,Y +7AA9- 45 DB EOR $DB +7AAB- 88 DEY +7AAC- 10 E7 BPL $7A95 +; +7AAE- A8 TAY +7AAF- D0 B7 BNE $7A68 ; chksum error +; Read epilogue (DE AA) +7AB1- BD 8C C0 LDA $C08C,X +7AB4- 10 FB BPL $7AB1 +7AB6- C9 DE CMP #$DE +7AB8- D0 AE BNE $7A68 ; error +7ABA- EA NOP +7ABB- BD 8C C0 LDA $C08C,X +7ABE- 10 FB BPL $7ABB +7AC0- C9 AA CMP #$AA +7AC2- D0 A4 BNE $7A68 ; error +7AC4- 18 CLC ; res = OK +7AC5- 60 RTS +; end + +; Seek to half track +; Pre: A=half track#, X=slot*16, Y=slot +7AC6- 8E 37 7D STX $7D37 +7AC9- 8D 36 7D STA $7D36 +7ACC- CD 24 7D CMP $7D24 +7ACF- F0 5C BEQ $7B2D +7AD1- A9 00 LDA #$00 +7AD3- 8D 38 7D STA $7D38 +7AD6- AD 24 7D LDA $7D24 +7AD9- 8D 39 7D STA $7D39 +7ADC- 38 SEC +7ADD- ED 36 7D SBC $7D36 +7AE0- F0 37 BEQ $7B19 +7AE2- B0 07 BCS $7AEB +7AE4- 49 FF EOR #$FF +7AE6- EE 24 7D INC $7D24 +7AE9- 90 05 BCC $7AF0 +7AEB- 69 FE ADC #$FE +7AED- CE 24 7D DEC $7D24 +7AF0- CD 38 7D CMP $7D38 +7AF3- 90 03 BCC $7AF8 +7AF5- AD 38 7D LDA $7D38 +7AF8- C9 0C CMP #$0C +7AFA- B0 01 BCS $7AFD +7AFC- A8 TAY +7AFD- 38 SEC +7AFE- 20 1D 7B JSR $7B1D +7B01- B9 4B 7C LDA $7C4B,Y +7B04- 20 3A 7C JSR $7C3A +7B07- AD 39 7D LDA $7D39 +7B0A- 18 CLC +7B0B- 20 20 7B JSR $7B20 +7B0E- B9 57 7C LDA $7C57,Y +7B11- 20 3A 7C JSR $7C3A +7B14- EE 38 7D INC $7D38 +7B17- D0 BD BNE $7AD6 +7B19- 20 3A 7C JSR $7C3A +7B1C- 18 CLC +7B1D- AD 24 7D LDA $7D24 +7B20- 29 03 AND #$03 +7B22- 2A ROL +7B23- 0D 37 7D ORA $7D37 +7B26- AA TAX +7B27- BD 80 C0 LDA $C080,X +7B2A- AE 37 7D LDX $7D37 +7B2D- 60 RTS +; end + +; +; Write gap2, Data field, data +; + +7B2E- 20 0E 7D JSR $7D0E +7B31- BD 8D C0 LDA $C08D,X +7B34- BD 8E C0 LDA $C08E,X + +; Write gap2 (5x 10-bit FF) +7B37- A9 FF LDA #$FF +7B39- 9D 8F C0 STA $C08F,X +7B3C- DD 8C C0 CMP $C08C,X +7B3F- 48 PHA +7B40- 68 PLA +7B41- EA NOP +7B42- A0 04 LDY #$04 +7B44- 48 PHA +7B45- 68 PLA +7B46- 20 A5 7B JSR $7BA5 +7B49- 88 DEY +7B4A- D0 F8 BNE $7B44 + +; Write Data prologue (D5 AA AD) +7B4C- A9 D5 LDA #$D5 +7B4E- 20 A4 7B JSR $7BA4 +7B51- A9 AA LDA #$AA +7B53- 20 A4 7B JSR $7BA4 +7B56- A9 AD LDA #$AD +7B58- 20 A4 7B JSR $7BA4 + +; Write 86 x #$96 +7B5B- A0 56 LDY #$56 +7B5D- EA NOP +7B5E- EA NOP +7B5F- EA NOP +7B60- D0 03 BNE $7B65 +7B62- 20 0E 7D JSR $7D0E ; RTS +7B65- EA NOP +7B66- EA NOP +7B67- A9 96 LDA #$96 +7B69- 9D 8D C0 STA $C08D,X +7B6C- DD 8C C0 CMP $C08C,X +7B6F- 88 DEY +7B70- D0 F0 BNE $7B62 + +; Write 256 x #$96 +7B72- 24 00 BIT $00 +7B74- EA NOP +7B75- 20 0E 7D JSR $7D0E ; RTS +7B78- A9 96 LDA #$96 +7B7A- 9D 8D C0 STA $C08D,X +7B7D- DD 8C C0 CMP $C08C,X +7B80- A9 96 LDA #$96 +7B82- EA NOP +7B83- C8 INY +7B84- D0 EF BNE $7B75 + +; Write Data epilogue (DE AA EB FF) +7B86- 20 A4 7B JSR $7BA4 +7B89- A9 DE LDA #$DE +7B8B- 20 A4 7B JSR $7BA4 +7B8E- A9 AA LDA #$AA +7B90- 20 A4 7B JSR $7BA4 +7B93- A9 EB LDA #$EB +7B95- 20 A4 7B JSR $7BA4 +7B98- A9 FF LDA #$FF +7B9A- 20 A4 7B JSR $7BA4 +; +7B9D- BD 8E C0 LDA $C08E,X ; read latch (and set read mode) +7BA0- BD 8C C0 LDA $C08C,X ; read latch +7BA3- 60 RTS + +; Write nibble +7BA4- EA NOP +; Write nibble +7BA5- 48 PHA +7BA6- 68 PLA +7BA7- 9D 8D C0 STA $C08D,X +7BAA- DD 8C C0 CMP $C08C,X +7BAD- 60 RTS + +; +; Write gap1(sector-0) or gap3 & address field +; Pre: X=slot*16, Y=gap count +; + +; Check if disk is write enabled +7BAE- 38 SEC ; ? (2 cycles) +7BAF- BD 8D C0 LDA $C08D,X ; load write protect to latch (b7) +7BB2- BD 8E C0 LDA $C08E,X ; read latch (and set read mode) +7BB5- 30 5E BMI $7C15 ; branch if write protected + +; Gap1 or Gap3: Initial 10-bit FF sync byte +7BB7- A9 FF LDA #$FF +7BB9- 9D 8F C0 STA $C08F,X ; set write mode & write data to latch +7BBC- DD 8C C0 CMP $C08C,X ; start writing latch (start shifting) +7BBF- 48 PHA +7BC0- 68 PLA + +; Gap1 or Gap3: 10-bit FF sync byte (40 cycle loop) +; Pre: A=#$FF, Y=gap count +7BC1- 20 1B 7C JSR $7C1B ; RTS +7BC4- 20 1B 7C JSR $7C1B ; RTS +7BC7- 9D 8D C0 STA $C08D,X ; write data to latch +7BCA- DD 8C C0 CMP $C08C,X ; start writing latch (start shifting) +7BCD- EA NOP +7BCE- 88 DEY +7BCF- D0 F0 BNE $7BC1 ; NB. branch taken cross pages + +; Write address prologue (D5 AA 96) +7BD1- A9 D5 LDA #$D5 +7BD3- 20 2D 7C JSR $7C2D +7BD6- A9 AA LDA #$AA +7BD8- 20 2D 7C JSR $7C2D +7BDB- A9 96 LDA #$96 +7BDD- 20 2D 7C JSR $7C2D + +; Write address field +7BE0- A5 D3 LDA $D3 ; Vol=01 +7BE2- 20 1C 7C JSR $7C1C +7BE5- A5 D1 LDA $D1 ; Trk +7BE7- 20 1C 7C JSR $7C1C +7BEA- A5 D2 LDA $D2 ; Sec +7BEC- 20 1C 7C JSR $7C1C +7BEF- A5 D3 LDA $D3 +7BF1- 45 D1 EOR $D1 +7BF3- 45 D2 EOR $D2 +7BF5- 48 PHA ; Chksum +7BF6- 4A LSR +7BF7- 05 D0 ORA $D0 ; OR with #$AA +; write 4&4 chksum in A +7BF9- 9D 8D C0 STA $C08D,X +7BFC- BD 8C C0 LDA $C08C,X +7BFF- 68 PLA +7C00- 09 AA ORA #$AA +7C02- 20 2C 7C JSR $7C2C + +; write address epilogue (DE AA EB) +7C05- A9 DE LDA #$DE +7C07- 20 2D 7C JSR $7C2D +7C0A- A9 AA LDA #$AA +7C0C- 20 2D 7C JSR $7C2D +7C0F- A9 EB LDA #$EB +7C11- 20 2D 7C JSR $7C2D +7C14- 18 CLC +7C15- BD 8E C0 LDA $C08E,X +7C18- BD 8C C0 LDA $C08C,X +7C1B- 60 RTS + +; write 4&4 byte in A +7C1C- 48 PHA +7C1D- 4A LSR +7C1E- 05 D0 ORA $D0 +7C20- 9D 8D C0 STA $C08D,X +7C23- DD 8C C0 CMP $C08C,X +7C26- 68 PLA +7C27- EA NOP +7C28- EA NOP +7C29- EA NOP +7C2A- 09 AA ORA #$AA +7C2C- EA NOP +; fall through... + +; 32 cycle write +7C2D- EA NOP +7C2E- 48 PHA +7C2F- 68 PLA +7C30- 9D 8D C0 STA $C08D,X +7C33- DD 8C C0 CMP $C08C,X +7C36- 60 RTS +; end + +; ??? (unused) +7C37- C8 INY +7C38- A0 C3 LDY #$C3 +; ??? (end) + +; Wait: A * (2 + (5*16) + 5+3+5+2+2+3) = A * 102 cycles (roughly) +; Pre: A = wait value +7C3A- A2 11 LDX #$11 ; 2cy +7C3C- CA DEX ; 2cy +7C3D- D0 FD BNE $7C3C ; 2+1 (branch taken) +7C3F- E6 D9 INC $D9 ; 5cy / read_trk++ +7C41- D0 02 BNE $7C45 ; 2+1 (branch taken) +7C43- E6 DA INC $DA ; 5cy / read_vol++ +7C45- 38 SEC ; 2cy +7C46- E9 01 SBC #$01 ; 2cy +7C48- D0 F0 BNE $7C3A ; 2+1 (branch taken) +7C4A- 60 RTS +; end + +.data +7C4B: ; 12 bytes + !byte $01,$30,$28 + !byte $24,$20,$1E + !byte $1D,$1C,$1C + !byte $1C,$1C,$1C +7C57: ; 12 bytes + !byte $70,$2C,$26 + !byte $22,$1F,$1E + !byte $1D,$1C,$1C + !byte $1C,$1C,$1C + +.code + +; +; Write track and verify track +; + +; write gap1 & address field +7C63- AD 21 7D LDA $7D21 +7C66- 85 D6 STA $D6 ; ($D6) = 3 = timeout * 256? +; +7C68- A0 80 LDY #$80 ; gap1 has gap count = 128 +7C6A- A9 00 LDA #$00 +7C6C- 85 D2 STA $D2 ; sector = 0 +7C6E- 4C 73 7C JMP $7C73 + +; write gap3 & address field +7C71- A4 D4 LDY $D4 ; gap3_count +; +7C73- AE 23 7D LDX $7D23 ; slot*16 +7C76- 20 AE 7B JSR $7BAE ; write gap1|3 & address field +7C79- 90 03 BCC $7C7E +; error: +7C7B- 4C 0E 7D JMP $7D0E +; success: +; write gap2, data field, data +7C7E- AE 23 7D LDX $7D23 +7C81- 20 2E 7B JSR $7B2E +7C84- E6 D2 INC $D2 ; inc write_sector +7C86- A5 D2 LDA $D2 +7C88- C9 10 CMP #$10 ; done 16 sectors? +7C8A- 90 E5 BCC $7C71 ; ... no, write next gap3 & sector + +; +; verify track +; + +7C8C- A0 0F LDY #$0F +7C8E- 84 D2 STY $D2 ; write_sector = 15 (used as sector loop counter) +7C90- AD 22 7D LDA $7D22 ; A = #$10 (constant) +7C93- 8D 25 7D STA $7D25 ; Set retry count = #$10 + +; Fill sector_flag struct with #$10 +7C96- 99 26 7D STA $7D26,Y +7C99- 88 DEY +7C9A- 10 FA BPL $7C96 + +7C9C- A5 D4 LDA $D4 ; gap3_count +7C9E- 38 SEC +7C9F- E9 05 SBC #$05 +7CA1- A8 TAY + +; Delay for: (gap3_count-5) * 40 cycles +7CA2- 20 0E 7D JSR $7D0E ; 12cy / RTS +7CA5- 20 0E 7D JSR $7D0E ; 12cy / RTS +7CA8- 48 PHA ; 3 +7CA9- 68 PLA ; 4 +7CAA- EA NOP ; 2 +7CAB- EA NOP ; 2 +7CAC- 88 DEY ; 2 +7CAD- D0 F3 BNE $7CA2 ; 3 (taken) + ; = 40 cycles + +7CAF- AE 23 7D LDX $7D23 +7CB2- 20 6A 7A JSR $7A6A ; Read address field +7CB5- B0 3C BCS $7CF3 +7CB7- A5 D8 LDA $D8 +7CB9- F0 13 BEQ $7CCE ; read sector 0? + ; ... No: +7CBB- C6 D4 DEC $D4 ; gap3_count-- +7CBD- A5 D4 LDA $D4 +7CBF- CD 1F 7D CMP $7D1F +7CC2- B0 2F BCS $7CF3 ; rewrite track +7CC4- 38 SEC ; error: gap3_count too small +7CC5- 60 RTS + +; Verify next sector +7CC6- AE 23 7D LDX $7D23 +7CC9- 20 6A 7A JSR $7A6A ; Read address field +7CCC- B0 1A BCS $7CE8 +; +7CCE- AE 23 7D LDX $7D23 +7CD1- 20 07 7A JSR $7A07 ; Read sector data +7CD4- B0 12 BCS $7CE8 +7CD6- A4 D8 LDY $D8 ; Y=read sector# +7CD8- B9 26 7D LDA $7D26,Y +7CDB- 30 0B BMI $7CE8 ; -ve if already read this sector +7CDD- A9 FF LDA #$FF +7CDF- 99 26 7D STA $7D26,Y ; sector_flag[Y] := #$FF +7CE2- C6 D2 DEC $D2 ; write_sector-- +7CE4- 10 E0 BPL $7CC6 +7CE6- 18 CLC ; res = OK +7CE7- 60 RTS +; +7CE8- CE 25 7D DEC $7D25 ; retry_count-- +7CEB- D0 D9 BNE $7CC6 +7CED- C6 D6 DEC $D6 +7CEF- D0 02 BNE $7CF3 +7CF1- 38 SEC ; error (timeout) +7CF2- 60 RTS + +; Retry 32 times to read sector #$0F +; On success: rewrite track +7CF3- AD 22 7D LDA $7D22 ; A = #$10 (constant) +7CF6- 0A ASL ; A = #$20 +7CF7- 8D 25 7D STA $7D25 ; Set retry count = #$20 +; +7CFA- AE 23 7D LDX $7D23 +7CFD- 20 6A 7A JSR $7A6A ; Read address field +7D00- B0 06 BCS $7D08 +7D02- A5 D8 LDA $D8 +7D04- C9 0F CMP #$0F ; read sector == #$0F? (ie. last sector on track) +7D06- F0 07 BEQ $7D0F ; ... yes: wait & rewrite track +7D08- CE 25 7D DEC $7D25 +7D0B- D0 ED BNE $7CFA +7D0D- 38 SEC ; error +7D0E- 60 RTS +; + +; wait for 214 x 32-cycle nibbles +7D0F- A2 D6 LDX #$D6 ; = 214 +7D11- 20 0E 7D JSR $7D0E ; 12cy / RTS +7D14- 20 0E 7D JSR $7D0E ; 12cy / RTS +7D17- 24 00 BIT $00 ; 3cy +7D19- CA DEX ; 2cy +7D1A- D0 F5 BNE $7D11 ; 3cy (2+1taken) + ; = 32 +; JMP to Write track and verify track +7D1C- 4C 68 7C JMP $7C68 +; end + +.data +7D1F: 0E ; min gap3 +7D20: 1B ; max gap3 (gap3 >= 0x1B means DRIVE TOO SLOW) +7D21: 03 ; timeout * 256 +7D22: 10 ; a constant +7D23: 80 ; slot*10 +7D24: A0 ; gets init'd to #$50 (80) +7D25: A0 ; retry count + +; sector_flag[16]: +7D26: A0 B1 C5 A0 +7D2A: A0 C4 A0 B0 +7D2E: 80 A0 A0 C3 +7D32: A0 A0 A0 A0 + +7D36: A0 +7D37: A0 +7D38: A0 +7D39: A0 + +; Symbol table: + D0 kAA + D1 w_Track + D2 w_Sector + D3 w_Volume + D4 w_Gap3Count + D5 r_Nib96Count + D6 r_NibCount1Hi + D7 r_Chksum + D8 r_Sector + D9 r_Track + DA r_Volume + DB r_TmpChksum + DC r_NibCount2Hi + DD r_Tmp4and4 + DE kVolNum01 +7900 FormatterDiskII +7923 SeekTrack +793A FormatDisk +7982 WriteNextTrack +79A2 WriteTrack +79B5 CheckGap3Count +79CB FindSector00Init +79D1 FindSector00Cont +79E7 VerifySector +79EF NextTrack +79F9 Done +7A07 ReadSectorData +7A6A ReadAddressField +7AC6 SeekHalfTrack +7B2E WriteGap2AndData +7BA4 WriteNibble1a +7BA5 WriteNibble1b +7BAE CheckWriteProt +7BB7 WriteGap0Or3AndAddress +7C2C WriteNibble2a +7C2D WriteNibble2b +7C37 Unused3 +7C3A WaitA +7C4B Data12_1 +7C57 Data12_2 +7C63 WriteAndVerifyTrack +7C68 WriteGap1AndAddress2 +7C71 WriteGap3AndAddress +7C8C VerifyTrack +7C96 ResetSectorFlags +7CA2 WaitGap3Count +7CBB DecGap3Count +7CC6 VerifyNextSector +7CCE VerifyNextSector2 +7CE8 Retry +7CF3 Retry2 +7CFA FindSector0FCont +7D0E RTS +7D0F RetryWait +7D1F kMinGap3 +7D20 kMaxGap3 +7D21 kNibCountHi +7D22 k10 +7D23 Slotx16 +7D24 HalfTrack +7D25 RetryCount +7D26 SectorFlags diff --git a/docs/DiskII Formatter/Formatter.dsk b/docs/DiskII Formatter/Formatter.dsk new file mode 100644 index 0000000000000000000000000000000000000000..fbd83260f950f452d140dc37b959f9c9803ff780 GIT binary patch literal 143360 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 zG6ETaj6g;pBajiu2xJ5@0vUmfKt>=VkP*lTWCSt-8G(#IMj#`Q5y%K+1Tq2{fs8;# zAR~|w$OvQvG6ETaj6g;pBajiu2xJ5@0vUmfKt>=VkP*lTWCSt-8G(#IMj#`Q5y%K+ z1Tq2{fs8;#AR~|w$OvQvG6ETaj6g;pBajiu2xJ5@0vUmfKt>=VkP*lTWCSt-8G(#I zMj#`Q5y%K+1Tq2{fs8;#AR~|w$OvQvG6ETaj6g;pBajiu2xJ5@0vUmfKt>=VkP*lT zWCSt-8G(#IMj#`Q5y%K+1Tq2{fs8;#AR~|w$OvQvG6ETaj6g;pBajiu2xJ5@0vUmf zKt>=VkP*lTWCSt-8G(#IMj#`Q5y%K+1Tq2{fs8;#AR~|w$OvQvG6ETaj6g;pBajiu z2xJ5@0vUmfKt>=VkP*lTWCSt-8G(#IMj#`Q5y%K+1Tq2{fs8;#AR~|w$OvQvG6ETa zj6g;pBajiu2xJ5@0vUmfKt>=VkP*lTWCSt-8G(#IMj#`Q5y%K+1Tq2{fs8;#AR~|w z$OvQvG6ETaj6g;pBajiu2xJ5@0vUmfKt>=VkP*lTWCSt-8G(#IMj#`Q5y%K+1Tq2{ zfs8;#AR~|w$OvQvG6ETaj6g;pBajiu2xJ5@0vUmfKt>=VkP*lTWCSt-8G(#IMj#`Q X5y%K+1Tq2{fs8;#AS3W66oLOA=_h|; literal 0 HcmV?d00001 diff --git a/docs/DiskII Formatter/apple3_SRC_Disk_Formatter.pdf b/docs/DiskII Formatter/apple3_SRC_Disk_Formatter.pdf new file mode 100644 index 0000000000000000000000000000000000000000..864a401d9427d5990b064ca3adbc04f6f5398069 GIT binary patch literal 69202 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 literal 0 HcmV?d00001 diff --git a/docs/DiskII Formatter/formatter.s b/docs/DiskII Formatter/formatter.s new file mode 100644 index 00000000..ff58084a --- /dev/null +++ b/docs/DiskII Formatter/formatter.s @@ -0,0 +1,1494 @@ + ORG $2000 ;Re-ORG as necessary + LST ON,S,ASYM,VSYM + SBTL 'DISK FORMAT & PREPARATION ROUTINE' + REP 50 +* +* APPLE'S PRODOS FORMATTING/DISK BUILDING MODULE +* +* VERSION 1.0.3 +* +* +* MODIFIED FOR COMPLIANCE WITH PRODOS TECHNOTE #16 +* AND, TO CONSOLIDATE BUILDDISK, AND FORMATTER. +* INTO ONE MODULE, ACCESSED WITH A SINGLE CALL. +* ALSO TO PROVIDE A MECHANISM FOR THE USER TO +* DETERMINE THE NUMBER OF BLOCKS ON THE DEVICE, +* AND WHETHER IT IS A DISK II, /RAM, OR OTHER. +* ON 10/17/85, BY PETE MC DONALD. +* +* COPYRIGHT APPLE COMPUTER, INC., 1982-85 +* + REP 50 +* +* ENTRY1: (ORG+$10) +* INITIALIZES THE SPECIFIED UNIT #. BY: +* -FORMATTING PHYSICAL MEDIA. IF IT CAN BE FORMATTED +* -WRITING BOOT LOADER IN BLOCKS 0,1 (EVEN IF IT IS +* NOT A DISK II). +* -CREATING VOLUME DIRECTORY IN BLOCKS 2,3,4,5 WITH +* THE NAME CONTAINED IN THE FIRST 16 BYTES OF THE MODULE. +* -ALLOCATING BIT MAP IN BLOCKS 6 AND UP. +* +* ON ENTRY, @ ENTRY1 (ORG+$10): +* A = THE UNIT NUMBER, IN THE FORMAT REQUIRED BY THE +* PRODOS WRITE BLOCK CALL. +* X/Y = THE ADDRESS OF A BUFFER OF AT LEAST 512 BYTES +* WHICH THIS ROUTINE CAN FREELY USE. X = THE +* LOW PART OF THE ADDRESS. +* THE FIRST 16 BYTES OF THE MODULE MUST CONTAIN THE DESIRED +* VOLUME NAME, WHERE THE FIRST BYTE CONTAINS THE LENGTH +* OF THE NAME (SHOULD BE 1 THRU 15) AND THE REMAINING 15 +* BYTES CONTAIN THE NAME (SHOULD BE A PROPER VOLUME +* NAME, WITH NO LEADING SLASH). THE ORIGINAL +* CONTENTS OF THESE 16 BYTES ARE 12 (THE LENGTH), AND THE +* NAME 'DEFAULT.NAME '. NO CHECKING IS DONE ON THESE +* 16 BYTES, BUT BIT 7 IS STRIPPED FROM EACH BYTE OF THE +* NAME. +* +* +* ON RETURN: +* Z IS UNDEFINED. +* C = THE ERROR STATUS: +* C = 0 INDICATES NO DETECTED ERRORS. +* C = 1 INDICATES AN ERROR, IN WHICH CASE THE ACCUMULATOR +* CONTAINS THE PRODOS ERROR CODE. +* A = 0 IF THERE WAS NO ERROR (C = 0), OR IT CONTAINS THE +* PRODOS ERROR CODE IF THERE WAS AN ERROR (C = 1). +* X AND Y ARE DESTROYED. +* THE FIRST 512 BYTES OF THE BUFFER ARE DESTROYED. +* 0-PAGE LOCATIONS 2 AND 3 HAVE BEEN USED, BUT HAVE BEEN RESTORED +* TO THEIR VALUES AT ENTRY. +* 0-PAGE LOCATIONS $42-$47 HAVE BEEN CHANGED AND NOT RESTORED. +* +* IF CALLED FOR A NON-EXISTENT DISK (INCLUDING SLOT 0), +* ERROR $28 WILL BE RETURNED. +* IF IT IS AN EXISTENT UNIT NUMBER, THE PROCESS BEGINS, +* AND OTHER ERRORS ARE THEN POSSIBLE. +* +* USES UNIT, ROM ID'S, AND DRIVER ADDRESS TO DETERIME SIZE +* THOSE DEVICES FOR WHICH THE SIZE IS GOTTEN BY +* A STATUS CALL TO THE SLOT'S ROM, THE DRIVE BIT IS +* PRESENT IN LOCATION $43 AND IS USED TO INDEX INTO THE +* DRIVER VECTOR TABLE. THEREFORE, THE 2 DRIVES IN A SLOT +* COULD BE DIFFERENT SIZES. +* + page + REP 50 +* +* ENTRY2 (ORG+$13): +* RETURNS THE SIZE AND WHETHER IS DISK II, /RAM, OR OTHER. +* +* ON ENTRY, @ ENTRY2 (ORG+$13): +* A = UNIT NUMBER, IN FORMAT REQUIRED BY PRODOS. +* X/Y = THE ADDRESS OF A BUFFER OF AT LEAST 512 BYTES, +* WHICH THIS ROUTINE CAN USE FREELY. X = THE +* LOW PART OF THE ADDRESS. +* +* +* ON RETURN: +* Z IS UNDEFINED. +* C = THE ERROR STATUS. +* C = 0, NO ERROR +* C = 1, AN ERROR WAS DETECTED. +* X = (SIZE lo) IF C = 0, X = UNDEFINED IF C = 1 +* Y = (SIZE HI) IF C = 0. IF C = 1 THEN y = undefined +* A = error code if C = 1: IF C = 0 then +* A = 0 FOR DISK II, A = 1 FOR /RAM, A = 2 FOR ALL OTHERS. +* +* THE FIRST 512 BYTES OF THE BUFFER ARE DESTROYED. +* ZERO PAGE LOCS 2 AND 3 HAVE BEEN USED, BUT HAVE +* BEEN RESTORED TO THEIR VALUES AT ENTRY. +* 0 - PAGE LOCATIONS 42-47, HAVE BEEN CHANGED AND +* NOT RESTORED. +* +* IF CALLED FOR NON EXISTENT DEVICE, ERROR $28 WILL BE RETURNED +* IF CALLED FOR EXISTENT DEVICE, PROCESS WILL BEGIN, AND THEN +* OTHER ERRORS ARE POSSIBLE. +* +* USES UNIT, ROM ID'S, AND DRIVER ADDRESS TO DETERIME SIZE +* THOSE DEVICES FOR WHICH THE SIZE IS GOTTEN BY +* A STATUS CALL TO THE SLOT'S ROM, THE DRIVE BIT IS +* PRESENT IN LOCATION $43 AND IS USED TO INDEX INTO THE +* DRIVER VECTOR TABLE. THEREFORE, THE 2 DRIVES IN A SLOT +* COULD BE DIFFERENT SIZES. +* + page + REP 50 +* +MLIENTRY EQU $BF00 ;MLI ENTRY POINT +DEVADRS01 EQU $BF10 ;DEVICE DRIVER VECTOR TABLE +DEVCNT EQU $BF31 ;ONLINE DEVICE COUNT +DEVLST EQU $BF32 ;ONLINE DEVICE LIST +DATELO EQU $BF90 ;DATE/TIME (4 BYTES) +KMVERSN EQU $BFFE ;MINIMUM VERSION # +KVERSION EQU $BFFF ;PRODOS VERSION +ENTRYB EQU $0D ;ENTRIES/BLOCK IN A DIRECTORY +ENTRYL EQU $27 ;DIRECTORY ENTRY LENGTH +* +* PAGE ZERO LOCATIONS +* +BUFFPTR EQU 2 ;AND 3 +DEVCMD EQU $42 +DEVUNIT EQU $43 +DEVBLK EQU $46 ;AND 47 +* +BUILDDISK EQU * +* +DUMSIZE DB 12 ;SIZE OF THE DUMMY NAME +DUMMYNAM ASC 'DEFAULT.NAME ' + page +* +* ACTUAL ENTRY POINTS ARE HERE +* +entry1 jmp form ;normal builddisk entry +entry2 jmp stat ;return device size and type. +* +* this performs the normal format and disk build operations +* +form jsr validate ;save regs/verify unit num + bcs out ;error go home zp restored by validate + jmp Build ;else do format/build +* +* returns device size in x/y y=hi, and a= 0 for DISK II, +* 1 for /RAM, 2 for all others./ +* +stat jsr validate ;save zp/validate unit # + bcs out ;error go home/zp restored by validate. + jsr getblks ;else get and return size/type of unit + stx loctemp ;save size hi for a sec + jsr error ;no error, but fix zp locs 2,3 + tax ;for the sake of consistency swap + tya ;regs around to conform with normal + ldy loctemp ;status call. +out rts ;bye +* +Validate STA UNITNUM1 ;SAVE THE PASSED UNIT NUMBER + STA UNITNUM2 ;SAVE THE PASSED UNIT NUMBER + STA UNITNUM3 ;SAVE THE PASSED UNIT NUMBER +* + AND #$F0 ;CLEAR LO BITS JUST IN CASE + STA UNITLEFT ;SAVE FOR LATER (LEFT JUSTIFIED) +* + LDA BUFFPTR ;SAVE CURRENT CONTENTS OF 0-PAGE LOCATIONS + STA SAVEZERO + LDA BUFFPTR+1 + STA SAVEZERO+1 +* + STX BUFFPTR ;SAVE PASSED BUFFER ADDRESS IN 0-PAGE + STY BUFFPTR+1 + STX LBUFFPTR ;ALSO SAVE IN LOCAL PARAMETER LIST + STY LBUFFPTR+1 +* + LDX DEVCNT ; POINT TO LAST ACTIVE DISK +LOOP LDA DEVLST,X ; GET BYTE FOR ACTIVE DISK + AND #$F0 ; CLEAR OUT DISKTYPE INDICATOR + CMP UNITLEFT ; FOUND OUR DISK? + BEQ FOUND ; YES + DEX ; NO, POINT TO NEXT DISK + BPL LOOP ; IF X HAS NOT GONE NEGATIVE, THERE ARE MORE DISKS +* +* DIDN'T FIND DISK. + LDA #$28 ; SIGNAL NO DEVICE + SEC ; SIGNAL ERROR + BCS ERROR ;ALWAYS +found clc + RTS +* +BUILD equ * + jsr doformat ;go format if can + bcs error ;taken if error during format. + jsr isitram ;is unitnum /RAM ?o-SD + BNE OKDISK ;NO +* + LDA #0 ;No error, but do nothing | + CLC ; since RAMDISK Format does it for us | + BCC ERROR ;ALWAYS | +* +okdisk equ * ;mod + lda UNITLEFT ;*mod* recover disktype + STA DISKTYPE ;SAVE FOR LATER + JSR MLIENTRY ;WRITE BOOT BLOCK 0 + DB $81 + DW BLK0PARM + BNE ERROR +* + JSR MLIENTRY ;WRITE BOOT BLOCK 1 + DB $81 + DW BLK1PARM + BNE ERROR +* + JSR ROOTBLK2 ;WRITE ROOT DIRECTORY BLK 2 + BCS ERROR + JSR ROOTBLKS ;WRITE ROOT DIRECTORY BLKS 3-5 + BCS ERROR + JSR BITMAPS ;WRITE BIT MAP IN BLKS 6 AND UP +* +ERROR LDX SAVEZERO ;RESTORE 0-PAGE LOCATIONS + STX BUFFPTR + LDX SAVEZERO+1 + STX BUFFPTR+1 +* + RTS +* +SAVEZERO DW 0 +DISKTYPE DB 0 ;LOW ORDER NIBBLE FROM DEVLST +* +BLK0PARM DB 3 ;3 PARAMETERS +UNITNUM1 DB 0 ;UNIT NUMBER FILLED IN FROM CALLER + DW BOOTZERO ;ADDRESS OF BOOT BLOCK + DW 0 ;WRITE TO BLOCK 0 +* +BLK1PARM DB 3 ;3 PARAMETERS +UNITNUM2 DB 0 ;UNIT NUMBER FILLED IN FROM CALLER + DW BOOTONE ;ADDRESS OF BOOT BLOCK + DW 1 ;WRITE TO BLOCK 1 + SBTL 'SETUP & WRITE ROOT DIRECTORY' +ROOTBLK2 EQU * + JSR MLIENTRY ;GET DATE/TIME + DB $82 + DW 0 +* CANNOT GENERATE AN ERROR FROM THIS CALL + JSR CLRBUFF ;CLEAR BUFFER + LDY #2 ;POINT TO FORWARD POINTER IN BUFFER + LDA #3 ;BLOCK 2 POINTS FORWARD TO BLOCK 3 + STA (BUFFPTR),Y +* + LDY #4+0 ;POINT TO STORAGE TYPE/NAME LENGTH + LDA DUMSIZE ;USE DUMMY NAME + ORA #$F0 ;OR IN THE DIRECTORY MARKER + STA (BUFFPTR),Y + LDX #0 ;POINT TO FIRST CHARACTER OF NAME +RTD1 EQU * + INY + LDA DUMMYNAM,X ;GET VOLUME NAME + AND #$7F ;NO HI BIT + STA (BUFFPTR),Y ;WRITE TO BUFR + INX + CPX DUMSIZE ;DONE? + BNE RTD1 ;NO +* + LDX #0 ;POINT TO DATE/TIME IN PRODOS + LDY #4+$18 ;POINT TO DATE/TIME IN BUFFER +RT2 LDA DATELO,X ;TRANSFER DATE/TIME TO BUFFER + STA (BUFFPTR),Y + INX + INY + CPX #4 + BNE RT2 +* + LDA KVERSION ;GET VERSION # FROM GLOBALS + STA (BUFFPTR),Y +* + INY + LDA KMVERSN ;AND MINIMUM VERSION # + STA (BUFFPTR),Y + INY + LDA #$C3 ;GET ACCESS BYTE VALUE + STA (BUFFPTR),Y + INY + LDA #ENTRYL ;GET ENTRY LENGTH + STA (BUFFPTR),Y + INY + LDA #ENTRYB ;GET ENTRIES/BLOCK + STA (BUFFPTR),Y + LDY #4+$23 ;POINT TO BITMAP PTR + LDA #6 + STA (BUFFPTR),Y + JSR GETBLKS ;GET TOTAL BLKS (A=LO,X=HI) + BCS RTRET ;QUIT ON ERROR + LDY #4+$25 ;POINT TO TOTAL BLOCKS IN BUFFER + STA (BUFFPTR),Y ;LO + STA TEMP ;ALSO STORE IN TEMP AND TEMP1 + INY + TXA + STA (BUFFPTR),Y ;HI + STA TEMP1 +* + LDA #1 ;SET UP TO WRITE BLOCK 2 (GETS INCREMENTED) + STA BLKNUM + JSR WRTBLK +RTRET RTS ;C=1 MEANS ERROR ON WRITE, ELSE GOOD +* +TEMP DB 0 +TEMP1 DB 0 + PAGE + REP 50 +* +* isitram - determine if chosen unit, is /ram +* +* if vector is $ff00, then is /ram. +* +* ENTRY: unitleft contains left justified unitnum +* EXIT: X unchanged, a,y scrambled +* is ram, z=1 +* not ram z=0 +* +isitram equ * + lda unitleft ;get justified unit number + lsr a ;right justify + lsr a + lsr a + jsr getvect ;get device driver address + bne notram ;taken if low order of vect not 0 + cpy #$FF ;is high byte $FF + bne notram ;if not is not /ram and z=0 return + lda #00 ;is /ram make z=1 +notram rts ;bye +* +* +* isitdiskII - is unit number a disk II +* use signature bytes in CN00 +* derive cn from unitleft +* ENtry: unitleft contains left just unitnum +* exit : z=1 is diskII +* z=0 not disKII +* a,x scramble +* y unchanged +* +isitdiskII equ * + lda unitleft ;get unit number + and #$70 ;extract slot number + lsr a ;move slot to low nibble. + lsr a + lsr a + lsr a + ora #$c0 ;append $C for a slot address + sta loadd+2 ;mod hi byte of lda to point to CNXX + ldx #3 ;init count of bytes to check +chklp lda dIIlocs,x ;get lowbyte of address to check + sta loadd+1 ;save at load instruction +loadd lda $C000 ; self modifying get byte at loc + cmp dIIids,x ;is it a DiskII signature ? + bne endDII ;taken if no + dex ;else check the next one + bpl chklp ;are there anymore ? + inx ;make z=1 +endDII rts ;bye z=0 is not DII, z=1, is dII +dIIids dfb $20,0,3,0 ;DiskII signatures, +dIIlocs dfb 1,3,5,$ff ;and thier respective locations. +* +* +* DOFORMAT-format physical disk media if possible +* +* If disk II, use formatter driver. +* If ram based. Or if Rom based with can format true, use +* device format call. +* If is Rom based, and can format is not true, then do nothing. +* called only after it has been determined that unit # is valid +* +* ENTRY: BUFFPTR, & BUFFPTR+1, are user passed buffer address. +* UNITLEFT contains left justified unit num. +* UNITNUM1, contains originally passed unit num. +* A=unitnum, X&Y=don't care. +* +* EXIT: Success a=0 c=0 x,y unknown. +* Failure, a=errnum, c=1, x,y unknown. +* if ROM call made, $42-$47, destroyed. +* +* +doformat equ * + jsr isitdiskII ;is unit a disk II + bne dforcont ;taken if not + ldx #$D ;init index/count-1 +savlp lda $d0,x ;save locs $D0 - $DD + sta locbuff,x + dex ;next one /any more ? + bpl savlp ;taken if yes + lda UNITLEFT ;get the original unit num + jsr FORMATTII ;format a disk II + php ;save error status + pha ;save error code (if any) + ldx #$D ;restore $d0 - $DD +reslp lda locbuff,x + sta $D0,x + dex ;next one /anymore ? + bpl reslp ;taken if yes. + pla ;recover Error code + plp ;and error status. + rts ;done bye +* +dforcont lda unitleft ;get unit num again + lsr a ;right justify + lsr a + lsr a + jsr getvect ;get vector to device driver. + sta devjmp ;save lowbyte + sty devjmp+1 ;and high byte for driver call. + tya ;get high byte of address + and #$f0 ;clear low nibble + cmp #$c0 ;does it point to $CN ? + bne dforcont1 ;taken if no.(is not ROM based) +* + sty modadd+2 ;set up LDA to point at attributes +modadd lda $C0FE ;modified by previous instruction. + and #$08 ;isolate can format bit. + bne dforcont1 ;taken if it supports formatting + clc ;does not, but no error, just return for + rts ;builddisk to write dir etc. +* +dforcont1 lda unitnum1 ;get back unit num + sta devunit ;save it for driver + lda #00 ;zero for + sta devblk ;block + sta devblk+1 ;and block hi + lda #03 ;get format command + sta devcmd ;save it for driver + sta $cfff ;turn off whoever has $c800 + lda $c08b ;switch language card in + lda $c08b + jsr asjmp ;jsr to jmp indirect to driver. + bit $c082 ;switch rom back in. + rts ;ret to continue build, with error if any +* +* GETBLKS - GET # OF BLOCKS ON DEVICE. +* +* IF IT'S A DISKII, BLOCKS ARE HARDCODED AT $118. IF +* is /RAM # blocks hardcoded at $7f. If is is an +* OTHER KIND OF DISK, NUMBER OF BLOCKS MAY BE IN +* $CNFC,FD. BUT IF THEY CONTAIN 0, THEN MUST CALL +* ROM CODE WITH STATUS REQUEST TO GET BLOCKS. +* +* ENTRY: UNITNUM1, UNITLEFT, AND DISKTYPE MUST BE SET. +* EXIT: Success: Carry = 0, X=HI,A=LO BLOCKS +* : Y=0 for DISK II, Y=1 for /RAM, Y=2 for all others. +* Failure: Carry = 1, Accum = error code +* : X and Y undefined +* If ROM call is made: $42-$47 destroyed +* + REP 50 +* +GETBLKS equ * ;was LDA DISKTYPE + jsr isitdiskII ;was CMP #DISKII + BNE DB1a ;NO + lda #0 ;save the fact that this is disk II + sta loctemp ;at a local temp + LDA #$18 ;YES, SIZE = 280 BLOCKS + LDX #1 + BNE DB2 ;ALWAYS +* +db1a equ * + jsr isitram ;is this /RAM ? + bne db1 ;taken if not + lda #1 ;save the fact that tis is /RAM + sta loctemp ;at a local temp + ldx #0 ;and there are $7f blocks + lda #$7f ;get them and reset z + bne db2 ;alwayss +* +* Not DISK II SO CHECK $CNFC-FD +* +DB1 LDA UNITLEFT ; get unit number (left justified) | + LSR A ; SHIFT UNIT NUMBER INTO TABLE INDEX | + LSR A ; | + LSR A ; | + STA UNITRIGHT ; save it | + JSR GETVECT ;GET DRIVER VECTOR FROM TABLE | +* +* mod to check if driver is in CN00, if not must ask size. +* + tya + and #$F0 ;clear all but high nibble of address + cmp #$c0 ;is it in rom space + bne ask ;taken if not in ROM +* +* + STY BUFFPTR+1 ;HI | + LDA #$FC + STA BUFFPTR ;LO + LDY #0 + LDA (BUFFPTR),Y + PHA + INY + LDA (BUFFPTR),Y + TAX + BNE DB3 ; if not zero, then size is hardwired + PLA ; get lo byte + BNE DB2 ; if not zero then return +ask JSR ASKSIZE ; need to go ask device for size + BCS RESTORE ; branch if error + lda #2 ;save the fact that this is a "other" + sta loctemp ;at a local temp + TXA ; get low byte + PHA ; save it + TYA ; get hi byte + TAX ; put in X + PLA ; get low byte back + bcc RESTORE ; GO RESTORE BUFFER POINTER AND EXIT +* +DB3 PLA +DB2 CLC ; clear carry to indicate success +RESTORE LDY LBUFFPTR ; RESTORE THE POINTER TO THE CALLER'S BUFFER + STY BUFFPTR + LDY LBUFFPTR+1 + STY BUFFPTR+1 + ldy loctemp ;get the kind of device anbd return it. + RTS +* +ASKSIZE EQU * ; ask device for size via status command + LDA #0 ; COMMAND BYTE = 0 (give status) + STA DEVCMD ; store in zero page parameters + STA DEVBLK ; block # + STA DEVBLK+1 + LDA UNITRIGHT ; get unit # (right justified) + JSR GETVECT ; | + STA DEVJMP ; | + STY DEVJMP+1 ; | + LDA UNITNUM1 ; get unit #, with possible low nibble junk + STA DEVUNIT + STA $CFFF + lda $c08b + lda $c08b + JSR ASJMP + bit $c082 + RTS +ASJMP JMP (DEVJMP) ; indirect jump to ROM entry + BRK +* +GETVECT EQU * ; | + TAY ;VECTOR INTO TABLE IN ACC ON ENTRY | + LDA DEVADRS01,Y ;GET LOW BYTE | + PHA ;SAVE IT | + LDA DEVADRS01+1,Y ;GET HI BYTE | + TAY ;SAVE IT IN Y | + PLA ;GET LO BYTE BACK | + RTS ; | +* +UNITLEFT DB 0 ; UNIT NUMBER +UNITRIGHT DB 0 ; reserve a byte for saving slot +DEVJMP DW 0 ; ADDRESS IN ROM +* + REP 50 +* +* WRTBLK -- INCREMENTS THE BLOCK NUMBER AND WRITES +* CURRENT BUFFER TO THAT BLOCK +* + REP 50 +* +WRTBLK EQU * + INC BLKNUM + JSR MLIENTRY + DB $81 ;BLOCK WRITE + DW PARMLIST + RTS +* +PARMLIST EQU * ;PARAMETER LIST FOR WRITING BLOCKS 2 AND UP + DB 3 ;PARM COUNT +UNITNUM3 DB 0 +LBUFFPTR DW 0 +BLKNUM DW 0 + PAGE + REP 50 +* +* ROOTBLKS - SETUP AND WRITE FORWARD & BACKWARD POINTERS +* INTO BLOCKS 3,4,5 OF ROOT DIRECTORY +* + REP 50 +* +ROOTBLKS EQU * + JSR CLRBUFF ;CLEAR OUT BUFFER AREA + LDA #2 ;BACKWARD POINTER FOR BLOCK 3 + LDX #4 ;FORWARD POINTER FOR BLOCK 3 + JSR BF1 ;WRITE BLOCK 3 TO DISK + BCS BF2 ;ERR + LDA #3 ;BACKWARD POINTER FOR BLOCK 4 + LDX #5 ;FORWARD POINTER FOR BLOCK 4 + JSR BF1 ;WRITE BLK 4 TO DISK + BCS BF2 ;ERR + LDA #4 ;BACKWARD POINTER FOR BLOCK 5 + LDX #0 ;FORWARD POINTER FOR BLOCK 5 +BF1 LDY #0 ;POINT TO BACKWARD POINTER + STA (BUFFPTR),Y ;STORE BACKWARD PTR IN BUFFER + LDY #2 ;POINT TO FORWARD POINTER + TXA + STA (BUFFPTR),Y ;STORE FORWARD PTR IN BUFFER + JSR WRTBLK ;CALL MLI FOR WRITE TO DISK +BF2 RTS ;C=1 ERR ON WRITE ELSE OK + SBTL 'SETUP AND WRITE BITMAP' + REP 50 +* +* CONVBLKS - CONVERT # OF BLOCKS ON DEVICE TO # OF +* BYTES TO SET IN BITMAP FOR NEWLY FORMATTED DISK. +* +* ENTER: TEMP = LO BLOCKS +* TEMP1 = HI BLOCKS +* +* EXIT: TEMP = LO BYTES +* TEMP1 = HI BYTES +* NBITS = EXTRA BITS +* + REP 50 +* +CONVBLKS EQU * + LDA TEMP ; get low order # of blocks + AND #$07 ; put remainder of bits in NBITS + STA NBITS + LDA TEMP ; mask out low bits + AND #$F8 ; so that ROR's work + CLC ; clear carry for first time + LDX #3 ; slide bits down 3 places +CNV1 ROR TEMP1 ; slide top bits down + ROR A ; slide bottom bits down + DEX + BNE CNV1 ; go back and do more + STA TEMP ; put back lower bits + RTS +* +NBITS DB 0 + PAGE + REP 50 +* +* BITMAPS - SETUP AND WRITE BIT MAPS TO NEWLY FORMATTED +* DISKS. WORKS FOR ARBITRARY-SIZED VOLUMES. +* +* INPUTS: +* TEMP,TEMP1 -- word containing # blocks in device +* +* OUTPUTS: +* TEMP,TEMP1 -- destroyed +* CARRY -- 0 -> success +* 1 -> failure, code in accumulator +* + REP 50 +* +BITMAPS EQU * + jsr convblks ;convert # blks to # of bytes & bits + LDA NBITS ;ANY EXTRA BITS? + BEQ BTMP1 ;BRANCH IF NOT + INC TEMP ;DO 1 MORE BYTE IN BITMAP + BNE BTMP1 ; IF THERE IS. + INC TEMP1 +BTMP1 EQU * + lda temp1 ; hi byte of # of bytes in bit map + clc + ror A ; get # of blocks in bit map (#/$200) + bcs used ; if carry set, then need another bit + ldx temp ; did we end on even block boundary? + beq used ; branch if so (carry clear) + sec ; otherwise, set carry for another bit +used adc #6 ; add in # bits for root dir & boot blks + pha ; save # of bits to mark as used + LDA NBITS + BEQ BTMP2 + DEC TEMP ;RESTORE # BYTES IN MAP TO # FULL BYTES + LDA TEMP + CMP #$FF + BNE BTMP2 + DEC TEMP1 +BTMP2 JSR CLRBUFF ;ZERO THE BUFFER +mapblock lda temp1 ; check # of bytes left TO DO + cmp #2 ; LESS THAN $200 BYTES to do? + bcc last ; go do last block if YES. + SBC #2 ;SET COUNT TO DO AT N-$200 + STA TEMP1 + jsr setfull ; set the full block with $FF's + pla ; get # of bits to mark used + jsr markused + jsr WRTBLK ; write this block of bit map out + bcs bterr ; branch if error during write + lda #0 ;# of bits to be marked as used next time + pha + beq BTMP2 ; always taken +last jsr CLRBUFF ; clear buffer first + lda temp1 ; 1 PAGE OR LESS? + beq last1 ;BRANCH IF YES + LDA #$FF + jsr WRTBITS ; set first page to $FF's + inc BUFFPTR+1 ; point to second page +LAST1 LDY TEMP ;ANY FULL BYTES ON THIS PG OF PARTIAL BLOCK? + BEQ LAST1.1 ;BRANCH IF NOT + jsr setCNT ; ELSE mark final partial block +LAST1.1 LDY TEMP + INY ;POINT TO BYTE AFTER TEMP + JSR EXTRAB ;GO DO EXTRA BITS + lda temp1 ; was it the in the 1st or 2nd page ? + beq marklast ; branch if 1st + dec BUFFPTR+1 ; fix BUFFPTR if we did 2nd page +marklast pla ; pull off # of bits to mark as used + jsr markused ; mark them used + jsr WRTBLK ; write out last block of bit map + rts ; return (with carry set if error) +* +markused equ * ; mark some bits as used at start of blk + ldy #0 ; point to beginning of buffer +markloop tax ; store # bits to mark in X + beq markrtn ; if no bits to mark as used, return + cpx #8 ; more than eight bits to mark? + bcc markpart ; branch if less than full byte + lda #0 ; zero out whole byte + sta (BUFFPTR),y + iny ; point to next byte in block + txa ; get # bits in accum + sec ; set carry for subtraction + sbc #8 ; subtract off bits just marked + bpl markloop ; always taken +markpart lda #$7F ; at least 1 bit gets cleared +partloop dex ; are we done? + beq partdone ; branch if so + clc ; otherwise, rotate in another clear bit + ror A + bcs partloop ; branch always +partdone sta (BUFFPTR),y +markrtn rts +* +bterr equ * ; return after error writing block + tax ; save error code in X + pla ; pull off extraneous byte from stack + txa ; get error code back + sec ; mark as error + rts +* +SETCNT EQU * ;SET # OF BYTES IN Y TO $FF + LDA #$FF +SETCNT1 DEY + STA (BUFFPTR),Y + BNE SETCNT1 + RTS +* +extrab lda nbits ; write leftover bits + beq ex1 ; none left over + jsr getbits ; gives mask in acc, leaves Y intact + DEY + sta (BUFFPTR),y +ex1 rts +* +CLRBUFF equ * ; clear buffer area + lda #0 ; | + BEQ WRTB1 ; | +SETFULL LDA #$FF ;FILL BUFFER W/$FF | +WRTB1 jsr wrtbits ; write out bits of 00's OR $FF's | + inc BUFFPTR+1 ; set to 2nd page of buffer + jsr wrtbits + dec BUFFPTR+1 ; restore pointer + rts +wrtbits ldy #0 +wrtb sta (BUFFPTR),Y + iny + bne wrtb + rts +* + REP 50 +* +* GETBITS - GET BIT MASK FOR REMAINING BITS. +* USED IN FORMAT FOR SETTING BITS IN VOLUME +* BIT MAPS. +* + REP 50 +* +GETBITS EQU * ;GET BIT MASK FOR REMAINING BYTE IN UIMEM + SEC + LDA #$08 + SBC NBITS + BEQ ALLBITS + TAX + CPX #8 + BEQ NOBITS + LDA #$FF +SHFBITS ASL A + DEX + BNE SHFBITS + BEQ SOMEBITS +ALLBITS LDA #$FF +SOMEBITS EQU * + RTS +NOBITS LDA #0 + BEQ SOMEBITS + SBTL 'BOOT BLOCK 0 AND 1 CODE' + REP 50 +* +* BOOT BLOCK 0 CODE +* + REP 50 +* +BOOTZERO EQU * ;WRITTEN TO BLOCK 0 + DFB $01,$38,$B0,$03,$4C,$32,$A1,$86 + DFB $43,$C9,$03,$08,$8A,$29,$70,$4A + DFB $4A,$4A,$4A,$09,$C0,$85,$49,$A0 + DFB $FF,$84,$48,$28,$C8,$B1,$48,$D0 + DFB $3A,$B0,$0E,$A9,$03,$8D,$00,$08 + DFB $E6,$3D,$A5,$49,$48,$A9,$5B,$48 + DFB $60,$85,$40,$85,$48,$A0,$63,$B1 + DFB $48,$99,$94,$09,$C8,$C0,$EB,$D0 + DFB $F6,$A2,$06,$BC,$1D,$09,$BD,$24 + DFB $09,$99,$F2,$09,$BD,$2B,$09,$9D + DFB $7F,$0A,$CA,$10,$EE,$A9,$09,$85 + DFB $49,$A9,$86,$A0,$00,$C9,$F9,$B0 + DFB $2F,$85,$48,$84,$60,$84,$4A,$84 + DFB $4C,$84,$4E,$84,$47,$C8,$84,$42 + DFB $C8,$84,$46,$A9,$0C,$85,$61,$85 + DFB $4B,$20,$12,$09,$B0,$68,$E6,$61 + DFB $E6,$61,$E6,$46,$A5,$46,$C9,$06 + DFB $90,$EF,$AD,$00,$0C,$0D,$01,$0C + DFB $D0,$6D,$A9,$04,$D0,$02,$A5,$4A + DFB $18,$6D,$23,$0C,$A8,$90,$0D,$E6 + DFB $4B,$A5,$4B,$4A,$B0,$06,$C9,$0A + DFB $F0,$55,$A0,$04,$84,$4A,$AD,$02 + DFB $09,$29,$0F,$A8,$B1,$4A,$D9,$02 + DFB $09,$D0,$DB,$88,$10,$F6,$29,$F0 + DFB $C9,$20,$D0,$3B,$A0,$10,$B1,$4A + DFB $C9,$FF,$D0,$33,$C8,$B1,$4A,$85 + DFB $46,$C8,$B1,$4A,$85,$47,$A9,$00 + DFB $85,$4A,$A0,$1E,$84,$4B,$84,$61 + DFB $C8,$84,$4D,$20,$12,$09,$B0,$17 + DFB $E6,$61,$E6,$61,$A4,$4E,$E6,$4E + DFB $B1,$4A,$85,$46,$B1,$4C,$85,$47 + DFB $11,$4A,$D0,$E7,$4C,$00,$20,$4C + DFB $3F,$09,$26,$50,$52,$4F,$44,$4F + DFB $53,$20,$20,$20,$20,$20,$20,$20 + DFB $20,$20,$A5,$60,$85,$44,$A5,$61 + DFB $85,$45,$6C,$48,$00,$08,$1E,$24 + DFB $3F,$45,$47,$76,$F4,$D7,$D1,$B6 + DFB $4B,$B4,$AC,$A6,$2B,$18,$60,$4C + DFB $BC,$09,$A9,$9F,$48,$A9,$FF,$48 + DFB $A9,$01,$A2,$00,$4C,$79,$F4,$20 + DFB $58,$FC,$A0,$1C,$B9,$50,$09,$99 + DFB $AE,$05,$88,$10,$F7,$4C,$4D,$09 + DFB $AA,$AA,$AA,$A0,$D5,$CE,$C1,$C2 + DFB $CC,$C5,$A0,$D4,$CF,$A0,$CC,$CF + DFB $C1,$C4,$A0,$D0,$D2,$CF,$C4,$CF + DFB $D3,$A0,$AA,$AA,$AA,$A5,$53,$29 + DFB $03,$2A,$05,$2B,$AA,$BD,$80,$C0 + DFB $A9,$2C,$A2,$11,$CA,$D0,$FD,$E9 + DFB $01,$D0,$F7,$A6,$2B,$60,$A5,$46 + DFB $29,$07,$C9,$04,$29,$03,$08,$0A + DFB $28,$2A,$85,$3D,$A5,$47,$4A,$A5 + DFB $46,$6A,$4A,$4A,$85,$41,$0A,$85 + DFB $51,$A5,$45,$85,$27,$A6,$2B,$BD + DFB $89,$C0,$20,$BC,$09,$E6,$27,$E6 + DFB $3D,$E6,$3D,$B0,$03,$20,$BC,$09 + DFB $BC,$88,$C0,$60,$A5,$40,$0A,$85 + DFB $53,$A9,$00,$85,$54,$A5,$53,$85 + DFB $50,$38,$E5,$51,$F0,$14,$B0,$04 + DFB $E6,$53,$90,$02,$C6,$53,$38,$20 + DFB $6D,$09,$A5,$50,$18,$20,$6F,$09 + DFB $D0,$E3,$A0,$7F,$84,$52,$08,$28 + DFB $38,$C6,$52,$F0,$CE,$18,$08,$88 + DFB $F0,$F5,$BD,$8C,$C0,$10,$FB,$00 + DFB $00,$00,$00,$00,$00,$00,$00,$00 + PAGE + REP 50 +* +* BOOT BLOCK 1 CODE +* + REP 50 +* +BOOTONE EQU * ;WRITTEN TO BLOCK 1 + DFB $4C,$6E,$A0,$53,$4F,$53,$20,$42 + DFB $4F,$4F,$54,$20,$20,$31,$2E,$31 + DFB $20,$0A,$53,$4F,$53,$2E,$4B,$45 + DFB $52,$4E,$45,$4C,$20,$20,$20,$20 + DFB $20,$53,$4F,$53,$20,$4B,$52,$4E + DFB $4C,$49,$2F,$4F,$20,$45,$52,$52 + DFB $4F,$52,$08,$00,$46,$49,$4C,$45 + DFB $20,$27,$53,$4F,$53,$2E,$4B,$45 + DFB $52,$4E,$45,$4C,$27,$20,$4E,$4F + DFB $54,$20,$46,$4F,$55,$4E,$44,$25 + DFB $00,$49,$4E,$56,$41,$4C,$49,$44 + DFB $20,$4B,$45,$52,$4E,$45,$4C,$20 + DFB $46,$49,$4C,$45,$3A,$00,$00,$0C + DFB $00,$1E,$0E,$1E,$04,$A4,$78,$D8 + DFB $A9,$77,$8D,$DF,$FF,$A2,$FB,$9A + DFB $2C,$10,$C0,$A9,$40,$8D,$CA,$FF + DFB $A9,$07,$8D,$EF,$FF,$A2,$00,$CE + DFB $EF,$FF,$8E,$00,$20,$AD,$00,$20 + DFB $D0,$F5,$A9,$01,$85,$E0,$A9,$00 + DFB $85,$E1,$A9,$00,$85,$85,$A9,$A2 + DFB $85,$86,$20,$BE,$A1,$E6,$E0,$A9 + DFB $00,$85,$E6,$E6,$86,$E6,$86,$E6 + DFB $E6,$20,$BE,$A1,$A0,$02,$B1,$85 + DFB $85,$E0,$C8,$B1,$85,$85,$E1,$D0 + DFB $EA,$A5,$E0,$D0,$E6,$AD,$6C,$A0 + DFB $85,$E2,$AD,$6D,$A0,$85,$E3,$18 + DFB $A5,$E3,$69,$02,$85,$E5,$38,$A5 + DFB $E2,$ED,$23,$A4,$85,$E4,$A5,$E5 + DFB $E9,$00,$85,$E5,$A0,$00,$B1,$E2 + DFB $29,$0F,$CD,$11,$A0,$D0,$21,$A8 + DFB $B1,$E2,$D9,$11,$A0,$D0,$19,$88 + DFB $D0,$F6,$A0,$00,$B1,$E2,$29,$F0 + DFB $C9,$20,$F0,$3E,$C9,$F0,$F0,$08 + DFB $AE,$64,$A0,$A0,$13,$4C,$D4,$A1 + DFB $18,$A5,$E2,$6D,$23,$A4,$85,$E2 + DFB $A5,$E3,$69,$00,$85,$E3,$A5,$E4 + DFB $C5,$E2,$A5,$E5,$E5,$E3,$B0,$BC + DFB $18,$A5,$E4,$6D,$23,$A4,$85,$E2 + DFB $A5,$E5,$69,$00,$85,$E3,$C6,$E6 + DFB $D0,$95,$AE,$4F,$A0,$A0,$1B,$4C + DFB $D4,$A1,$A0,$11,$B1,$E2,$85,$E0 + DFB $C8,$B1,$E2,$85,$E1,$AD,$66,$A0 + DFB $85,$85,$AD,$67,$A0,$85,$86,$20 + DFB $BE,$A1,$AD,$68,$A0,$85,$85,$AD + DFB $69,$A0,$85,$86,$AD,$00,$0C,$85 + DFB $E0,$AD,$00,$0D,$85,$E1,$20,$BE + DFB $A1,$A2,$07,$BD,$00,$1E,$DD,$21 + DFB $A0,$F0,$08,$AE,$64,$A0,$A0,$13 + DFB $4C,$D4,$A1,$CA,$10,$ED,$A9,$00 + DFB $85,$E7,$E6,$E7,$E6,$86,$E6,$86 + DFB $A6,$E7,$BD,$00,$0C,$85,$E0,$BD + DFB $00,$0D,$85,$E1,$A5,$E0,$D0,$04 + DFB $A5,$E1,$F0,$06,$20,$BE,$A1,$4C + DFB $8A,$A1,$18,$AD,$6A,$A0,$6D,$08 + DFB $1E,$85,$E8,$AD,$6B,$A0,$6D,$09 + DFB $1E,$85,$E9,$6C,$E8,$00,$A9,$01 + DFB $85,$87,$A5,$E0,$A6,$E1,$20,$79 + DFB $F4,$B0,$01,$60,$AE,$32,$A0,$A0 + DFB $09,$4C,$D4,$A1,$84,$E7,$38,$A9 + DFB $28,$E5,$E7,$4A,$18,$65,$E7,$A8 + DFB $BD,$29,$A0,$99,$A7,$05,$CA,$88 + DFB $C6,$E7,$D0,$F4,$AD,$40,$C0,$4C + DFB $EF,$A1,$00,$00,$00,$00,$00,$00 + DFB $00,$00,$00,$00,$00,$00,$00,$00 + DFB $00,$00,$03,$00,$F6,$50,$52,$4F +loctemp dfb 0 +locbuff ds $E,0 +ZBDEND EQU * +poslo equ >ZBDEND ;extract lowbyte of current pc +ZBDLEN EQU ZBDEND-BUILDDISK ;length of Buildisk, less formatter + ds $100-poslo ;fill to next page boundry + sbtl 'Disk II FORMATTER' + page +FORMATTII equ * ;here is the diskII formatter. +* +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * +* * * * * * * * * * * * * * * * * * * * * * * * * * * * +* * * * +* * M U S T B E O N P A G E B O U N D A R Y * * +* * * * +* * * * * * * * * * * * * * * * * * * * * * * * * * * * +* * * * * * * * * * * * * * * * * * * * * * * * * * * * +* * +* ProDOS DISK ][ Formatter Device Driver * +* * +* Copyright Apple Computer, Inc., 1982-1984 * +* * +* Enter with ProDOS device number in A-register: * +* Zero = bits 0, 1, 2, 3 * +* Slot No.= bits 4, 5, 6 * +* Drive 1 = bit 7 off * +* Drive 2 = bit 7 on * +* * +* Error codes returned in A-register: * +* $00 : Good completion * +* $27 : Unable to format * +* $2B : Write-Protected * +* $33 : Drive too SLOW * +* $34 : Drive too FAST * +* NOTE: Carry flag is set if error occured. * +* * +* Uses zero page locations $D0 thru $DD * +* * +* - - - - - - - - - - - - - - - - - - - - - - - - - - * +* Modified 15 December 1983 to disable interrupts * +* Modified 20 December 1983 to increase tolerance * +* of disk speed check * +* Modified 30 March 1983 to increase tolerance of * +* disk speed * +* * * * * * * * * * * * * * * * * * * * * * * * * * * * + PHP + SEI + JSR *+$38 + PLP + CMP #$00 + BNE *+$04 + CLC + RTS + CMP #$02 + BNE *+$07 + LDA #$2B + JMP *+$0F + CMP #$01 + BNE *+$07 + LDA #$27 + JMP *+$06 + CLC + ADC #$30 + SEC + RTS + ASL A + ASL *+$400 + STA *+$40F + TXA + LSR A + LSR A + LSR A + LSR A + TAY + LDA *+$406 + JSR *+$193 + LSR *+$3EE + RTS + TAX + AND #$70 + STA *+$3E6 + TXA + LDX *+$3E2 + ROL A + LDA #$00 + ROL A + BNE *+$08 + LDA $C08A,X + JMP *+$06 + LDA $C08B,X + LDA $C089,X + LDA #$D7 + STA $DA + LDA #$50 + STA *+$3C8 + LDA #$00 + JSR *-$3E + LDA $DA + BEQ *+$08 + JSR *+$2D2 + JMP *-$07 + LDA #$01 + STA $D3 + LDA #$AA + STA $D0 + LDA *+$3AA + CLC + ADC #$02 + STA $D4 + LDA #$00 + STA $D1 + LDA $D1 + LDX *+$39F + JSR *-$64 + LDX *+$399 + LDA $C08D,X + LDA $C08E,X + TAY + LDA $C08E,X + LDA $C08C,X + TYA + BPL *+$07 + LDA #$02 + JMP *+$5A + JSR *+$2C1 + BCC *+$10 + LDA #$01 + LDY $D4 + CPY *+$374 + BCS *+$04 + LDA #$04 + JMP *+$47 + LDY $D4 + CPY *+$368 + BCS *+$07 + LDA #$04 + JMP *+$3B + CPY *+$35F + BCC *+$07 + LDA #$03 + JMP *+$31 + LDA *+$357 + STA *+$357 + DEC *+$354 + BNE *+$07 + LDA #$01 + JMP *+$21 + LDX *+$348 + JSR *+$8C + BCS *-$10 + LDA $D8 + BNE *-$14 + LDX *+$33C + JSR *+$1D + BCS *-$1C + INC $D1 + LDA $D1 + CMP #$23 + BCC *-$73 + LDA #$00 + PHA + LDX *+$329 + LDA $C088,X + LDA #$00 + JSR *-$DF + PLA + RTS + LDY #$20 + DEY + BEQ *+$5E + LDA $C08C,X + BPL *-$03 + EOR #$D5 + BNE *-$0A + NOP + LDA $C08C,X + BPL *-$03 + CMP #$AA + BNE *-$0C + LDY #$56 + LDA $C08C,X + BPL *-$03 + CMP #$AD + BNE *-$17 + LDA #$00 + DEY + STY $D5 + LDA $C08C,X + BPL *-$03 + CMP #$96 + BNE *+$32 + LDY $D5 + BNE *-$0E + STY $D5 + LDA $C08C,X + BPL *-$03 + CMP #$96 + BNE *+$23 + LDY $D5 + INY + BNE *-$0E + LDA $C08C,X + BPL *-$03 + CMP #$96 + BNE *+$15 + LDA $C08C,X + BPL *-$03 + CMP #$DE + BNE *+$0C + NOP + LDA $C08C,X + BPL *-$03 + CMP #$AA + BEQ *+$5E + SEC + RTS + LDY #$FC + STY $DC + INY + BNE *+$06 + INC $DC + BEQ *-$0B + LDA $C08C,X + BPL *-$03 + CMP #$D5 + BNE *-$0E + NOP + LDA $C08C,X + BPL *-$03 + CMP #$AA + BNE *-$0C + LDY #$03 + LDA $C08C,X + BPL *-$03 + CMP #$96 + BNE *-$17 + LDA #$00 + STA $DB + LDA $C08C,X + BPL *-$03 + ROL A + STA $DD + LDA $C08C,X + BPL *-$03 + AND $DD + STA $D7,Y + EOR $DB + DEY + BPL *-$17 + TAY + BNE *-$47 + LDA $C08C,X + BPL *-$03 + CMP #$DE + BNE *-$50 + NOP + LDA $C08C,X + BPL *-$03 + CMP #$AA + BNE *-$5A + CLC + RTS + STX *+$271 + STA *+$26D + CMP *+$258 + BEQ *+$5E + LDA #$00 + STA *+$265 + LDA *+$24E + STA *+$260 + SEC + SBC *+$259 + BEQ *+$39 + BCS *+$09 + EOR #$FF + INC *+$23E + BCC *+$07 + ADC #$FE + DEC *+$237 + CMP *+$248 + BCC *+$05 + LDA *+$243 + CMP #$0C + BCS *+$03 + TAY + SEC + JSR *+$1F + LDA *+$14A,Y + JSR *+$136 + LDA *+$232 + CLC + JSR *+$15 + LDA *+$149,Y + JSR *+$129 + INC *+$224 + BNE *-$41 + JSR *+$121 + CLC + LDA *+$207 + AND #$03 + ROL A + ORA *+$214 + TAX + LDA $C080,X + LDX *+$20D + RTS + JSR *+$1E0 + LDA $C08D,X + LDA $C08E,X + LDA #$FF + STA $C08F,X + CMP $C08C,X + PHA + PLA + NOP + LDY #$04 + PHA + PLA + JSR *+$5F + DEY + BNE *-$06 + LDA #$D5 + JSR *+$56 + LDA #$AA + JSR *+$51 + LDA #$AD + JSR *+$4C + LDY #$56 + NOP + NOP + NOP + BNE *+$05 + JSR *+$1AC + NOP + NOP + LDA #$96 + STA $C08D,X + CMP $C08C,X + DEY + BNE *-$0E + BIT $00 + NOP + JSR *+$199 + LDA #$96 + STA $C08D,X + CMP $C08C,X + LDA #$96 + NOP + INY + BNE *-$0F + JSR *+$1E + LDA #$DE + JSR *+$19 + LDA #$AA + JSR *+$14 + LDA #$EB + JSR *+$0F + LDA #$FF + JSR *+$0A + LDA $C08E,X + LDA $C08C,X + RTS + NOP + PHA + PLA + STA $C08D,X + CMP $C08C,X + RTS + SEC + LDA $C08D,X + LDA $C08E,X + BMI *+$60 + LDA #$FF + STA $C08F,X + CMP $C08C,X + PHA + PLA + JSR *+$5A + JSR *+$57 + STA $C08D,X + CMP $C08C,X + NOP + DEY + BNE *-$0E + LDA #$D5 + JSR *+$5A + LDA #$AA + JSR *+$55 + LDA #$96 + JSR *+$50 + LDA $D3 + JSR *+$3A + LDA $D1 + JSR *+$35 + LDA $D2 + JSR *+$30 + LDA $D3 + EOR $D1 + EOR $D2 + PHA + LSR A + ORA $D0 + STA $C08D,X + LDA $C08C,X + PLA + ORA #$AA + JSR *+$2A + LDA #$DE + JSR *+$26 + LDA #$AA + JSR *+$21 + LDA #$EB + JSR *+$1C + CLC + LDA $C08E,X + LDA $C08C,X + RTS + PHA + LSR A + ORA $D0 + STA $C08D,X + CMP $C08C,X + PLA + NOP + NOP + NOP + ORA #$AA + NOP + NOP + PHA + PLA + STA $C08D,X + CMP $C08C,X + RTS + BRK + BRK + BRK + LDX #$11 + DEX + BNE *-$01 + INC $D9 + BNE *+$04 + INC $DA + SEC + SBC #$01 + BNE *-$0E + RTS + DFB $01,$30,$28 + DFB $24,$20,$1E + DFB $1D,$1C,$1C + DFB $1C,$1C,$1C + DFB $70,$2C,$26 + DFB $22,$1F,$1E + DFB $1D,$1C,$1C + DFB $1C,$1C,$1C + LDA *+$BE + STA $D6 + LDY #$80 + LDA #$00 + STA $D2 + JMP *+$05 + LDY $D4 + LDX *+$B0 + JSR *-$C8 + BCC *+$05 + JMP *+$93 + LDX *+$A5 + JSR *-$153 + INC $D2 + LDA $D2 + CMP #$10 + BCC *-$19 + LDY #$0F + STY $D2 + LDA *+$92 + STA *+$92 + STA *+$90,Y + DEY + BPL *-$04 + LDA $D4 + SEC + SBC #$05 + TAY + JSR *+$6C + JSR *+$69 + PHA + PLA + NOP + NOP + DEY + BNE *-$0B + LDX *+$74 + JSR *-$248 + BCS *+$3E + LDA $D8 + BEQ *+$15 + DEC $D4 + LDA $D4 + CMP *+$60 + BCS *+$31 + SEC + RTS + LDX *+$5D + JSR *-$25F + BCS *+$1C + LDX *+$55 + JSR *-$2CA + BCS *+$14 + LDY $D8 + LDA *+$4E,Y + BMI *+$0D + LDA #$FF + STA *+$47,Y + DEC $D2 + BPL *-$1E + CLC + RTS + DEC *+$3D + BNE *-$25 + DEC $D6 + BNE *+$04 + SEC + RTS + LDA *+$2F + ASL A + STA *+$2E + LDX *+$29 + JSR *-$293 + BCS *+$08 + LDA $D8 + CMP #$0F + BEQ *+$09 + DEC *+$1D + BNE *-$11 + SEC + RTS + LDX #$D6 + JSR *-$03 + JSR *-$06 + BIT $00 + DEX + BNE *-$09 + JMP *-$B4 + DFB $0E,$1B,$03 + DFB $10,$00,$00 + DFB $00,$00,$00 + DFB $00,$00,$00 + DFB $00,$00,$00 + DFB $00,$00,$00 + DFB $00,$00,$00 + DFB $00,$00,$00 + DFB $00,$00,$00 +Zend equ * +Ztotal equ Zend-Builddisk