From 16bc27fa1c80a82ecc0b25bf97687626663b760b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20GIBERT?= Date: Wed, 16 Oct 2019 08:09:13 +0200 Subject: [PATCH] Kernel 0.93+ --- .Floppies/A2OSX.BUILD.po | Bin 33553920 -> 33553920 bytes BIN/PAK.S.txt | 2 +- INC/LIBPAK.I.txt | 4 +- LIB/LIBPAK.S.txt | 14 +- ProDOS.FX/ProDOS.S.CCLK.txt | 65 +++ ProDOS.FX/ProDOS.S.GP.txt | 151 ++++++ ProDOS.FX/ProDOS.S.IRQ.txt | 71 +++ ProDOS.FX/ProDOS.S.LDR.A.txt | 742 ++++++++++++++++++++++++++ ProDOS.FX/ProDOS.S.LDR.B.txt | 942 ++++++++++++++++++++++++++++++++++ ProDOS.FX/ProDOS.S.RAM.txt | 88 ++++ ProDOS.FX/ProDOS.S.RAMX.txt | 322 ++++++++++++ ProDOS.FX/ProDOS.S.SEL0.txt | 297 +++++++++++ ProDOS.FX/ProDOS.S.SEL1.txt | 404 +++++++++++++++ ProDOS.FX/ProDOS.S.SEL2.txt | 440 ++++++++++++++++ ProDOS.FX/ProDOS.S.TCLK.txt | 104 ++++ ProDOS.FX/ProDOS.S.XDOS.A.txt | 670 ++++++++++++++++++++++++ ProDOS.FX/ProDOS.S.XDOS.B.txt | 890 ++++++++++++++++++++++++++++++++ ProDOS.FX/ProDOS.S.XDOS.C.txt | 720 ++++++++++++++++++++++++++ ProDOS.FX/ProDOS.S.XDOS.D.txt | 576 +++++++++++++++++++++ ProDOS.FX/ProDOS.S.XDOS.E.txt | 603 ++++++++++++++++++++++ ProDOS.FX/ProDOS.S.XDOS.F.txt | 765 +++++++++++++++++++++++++++ ProDOS.FX/ProDOS.S.XRW.txt | 882 +++++++++++++++++++++++++++++++ ProDOS.FX/ProDOS.S.txt | 228 ++++++++ SHARED/X.UNPAK.S.txt | 25 +- 24 files changed, 8985 insertions(+), 20 deletions(-) create mode 100644 ProDOS.FX/ProDOS.S.CCLK.txt create mode 100644 ProDOS.FX/ProDOS.S.GP.txt create mode 100644 ProDOS.FX/ProDOS.S.IRQ.txt create mode 100644 ProDOS.FX/ProDOS.S.LDR.A.txt create mode 100644 ProDOS.FX/ProDOS.S.LDR.B.txt create mode 100644 ProDOS.FX/ProDOS.S.RAM.txt create mode 100644 ProDOS.FX/ProDOS.S.RAMX.txt create mode 100644 ProDOS.FX/ProDOS.S.SEL0.txt create mode 100644 ProDOS.FX/ProDOS.S.SEL1.txt create mode 100644 ProDOS.FX/ProDOS.S.SEL2.txt create mode 100644 ProDOS.FX/ProDOS.S.TCLK.txt create mode 100644 ProDOS.FX/ProDOS.S.XDOS.A.txt create mode 100644 ProDOS.FX/ProDOS.S.XDOS.B.txt create mode 100644 ProDOS.FX/ProDOS.S.XDOS.C.txt create mode 100644 ProDOS.FX/ProDOS.S.XDOS.D.txt create mode 100644 ProDOS.FX/ProDOS.S.XDOS.E.txt create mode 100644 ProDOS.FX/ProDOS.S.XDOS.F.txt create mode 100644 ProDOS.FX/ProDOS.S.XRW.txt create mode 100644 ProDOS.FX/ProDOS.S.txt diff --git a/.Floppies/A2OSX.BUILD.po b/.Floppies/A2OSX.BUILD.po index 28d3e3c5373245a95d15dd05720f93c1baed0fcb..9878e7dea87bd75ccca487fcfe5584551d1c31b5 100644 GIT binary patch delta 14690 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.G Shunk.DstSize+1 jsr CS.RUN.WriteArcByteA bcs .9 - >DEBUG + >PUSHW.G Shunk.DstSize >PUSHW ZPDstBufPtr >LDA.G hArcFile diff --git a/INC/LIBPAK.I.txt b/INC/LIBPAK.I.txt index 6c66223d..a3634b02 100644 --- a/INC/LIBPAK.I.txt +++ b/INC/LIBPAK.I.txt @@ -26,8 +26,8 @@ PAK.B.BL .EQ %1111 * WORD : Target UNCompressed Length * !!! USED TO STOP UNPACK,NO EOF TOKEN!!! *-------------------------------------- -S.PAKSHNK.ULEN .EQ 0 Uncompressed length -S.PAKSHNK.BLBITS .EQ 2 1.lll.oooo +S.PAKSHNK.BLBITS .EQ 0 1.lll.oooo +S.PAKSHNK.ULEN .EQ 1 Uncompressed length S.PAKSHNK.TOPCNT .EQ 3 S.PAKSHNK.TOPBYTES .EQ 4 * TOP Bytes .... diff --git a/LIB/LIBPAK.S.txt b/LIB/LIBPAK.S.txt index 3349cac3..4139cc51 100644 --- a/LIB/LIBPAK.S.txt +++ b/LIB/LIBPAK.S.txt @@ -95,6 +95,9 @@ Pak >PULLW Pak.SrcPtr jsr Pak.Run bcs .9 + jsr Pak.Out.Close + bcs .9 + .DO STATS=1 jsr Pak.PrintStats >DEBUG @@ -482,7 +485,11 @@ Pak.PutByte8.2 ldy Pak.Shnk+S.PAKSHNK.TOPCNT .9 rts *-------------------------------------- -Pak.Out.Init lda Pak.Shnk+S.PAKSHNK.ULEN +Pak.Out.Init lda Pak.Shnk+S.PAKSHNK.BLBITS + jsr Pak.Out.PutByte + bcs .9 + + lda Pak.Shnk+S.PAKSHNK.ULEN jsr Pak.Out.PutByte bcs .9 @@ -490,10 +497,6 @@ Pak.Out.Init lda Pak.Shnk+S.PAKSHNK.ULEN jsr Pak.Out.PutByte bcs .9 - lda Pak.Shnk+S.PAKSHNK.BLBITS - jsr Pak.Out.PutByte - bcs .9 - lda Pak.Shnk+S.PAKSHNK.TOPCNT jsr Pak.Out.PutByte bcs .9 @@ -574,6 +577,7 @@ Pak.Out.PutByte inc Pak.DstCnt .1 sta (ZPDstPtr) inc ZPDstPtr + bne .2 inc ZPDstPtr+1 diff --git a/ProDOS.FX/ProDOS.S.CCLK.txt b/ProDOS.FX/ProDOS.S.CCLK.txt new file mode 100644 index 00000000..d6fd5a39 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.CCLK.txt @@ -0,0 +1,65 @@ +NEW + AUTO 3,1 +* object code = cclock_0 +* Cortland clock driver +* $2F80-$2FFC moved to $D742 +*-------------------------------------- +CCLK.START >SHORTMX 8 bit mode. + lda statereg state register. + sta savestate save for restore after tool call. + and #$CF clear the read/write aux memory bits. + sta statereg make it real + clc set e = 0 to set native mode + xce + >LONGMX 16 bit mode. + lda ##$0000 zero out result space. + pha push 4 words for hex time result + pha + pha + pha + >IIGS ReadTimeHex + >SHORTM back to 8 bit to get results from stack + lda savestate restore state register + sta statereg + pla pull off seconds and ignore + pla + sta p8time minutes + pla + sta p8time+1 hours + pla year +.1 cmp #100 out of range? + bcc .2 no, go ahead and store + sbc #$64 else put back in range. + bra .1 try again + +.2 sta p8date+1 year + pla + inc increment day for Prodos 8 format. + sta p8date day + pla month + inc increment month for Prodos 8 format. + asl shift month as it sits in between + asl the year and day values. + asl + asl + asl + ora p8date put all but the top bit of month + sta p8date value in the day byte. + rol p8date+1 put hi bit of month in low bit of year + pla pull of unused byte + pla pull off day of week. stack now clean. + sec go back to emulation mode + xce to continue with Prodos 8 + rts +savestate .HS 00 state of the state register + .AS "JIMJAYKERRY&MIKE" + .HS 0000000000000000 pad 0's until length + .HS 0000000000000000 of driver = 125 bytes. + .HS 000000000000 +CCLK.END .EQ * end of obj cclock_0. + .HS 000000 pad to page boundary +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.CCLK +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.GP.txt b/ProDOS.FX/ProDOS.S.GP.txt new file mode 100644 index 00000000..13e6fbc8 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.GP.txt @@ -0,0 +1,151 @@ +NEW + AUTO 3,1 +* object code = mli_1 +* global page + +H2E00 jmp mlient1 $2E00-2EFF moved to $BF00 +jspare jmp * will be changed to point to dispatcher. +clockv rts changed to jmp ($4C) if clock present. + .DA tclk_in clock routine entry address. +GP.P8errv jmp XDOS.syserr error reporting hook. +sysdeath jmp sysdeath1 system failure hook. +p8error .DA #0 +drivertbl1 .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice +drivertbl2 .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice + .DA nodevice + .DA #0 devnum +numdevs .DA #$ff count (-1) active devices +devlist .HS 00000000000000 up to 14 units may be active + .HS 00000000000000 + .DA #0 + + .AS "(C)APPLE " +mlient1 php + sei + jmp mlicont +aftirq sta RRAMWRAMBNK1 read/write RAM bank 1 + jmp fix45 restore $45 after interrupt in LC +oldacc .DA #0 +afbank .HS 00 + +* memory map of lower 48k. each bit represents 1 page. +* protected pages = 1, unprotected = 0 + +memmap .HS C000000000000000 + .HS 0000000000000000 + .HS 0000000000000001 + +* table of buffer addresses for currently open files. +* these can only be changed thru the mli call setbuf. + +buftbl .HS 0000 file #1 + .HS 0000 file #2 + .HS 0000 file #3 + .HS 0000 file #4 + .HS 0000 file #5 + .HS 0000 file #6 + .HS 0000 file #7 + .HS 0000 file #8 + +* table of interrupt vectors. these can only be changed +* by the mli call allocate_interrupt. values of the registers +* at the time of the most recent interrupt are stored here along +* with the address interrupted. + +inttbl .HS 0000 int #1 + .HS 0000 int #2 + .HS 0000 int #3 + .HS 0000 int #4 +p8areg .DA #0 A register savearea +p8xreg .DA #0 X register savearea +p8yreg .DA #0 Y register savearea +p8sreg .DA #0 S register savearea +p8preg .DA #0 P register savearea +bankid .DA #1 bank ID byte (ROM/RAM) +intadr .HS 0000 interrupt return address +p8date .HS 0000 bits 15-9=yr, 8-5=mo, 4-0=day +p8time .HS 0000 bits 12-8=hr, 5-0=min, low-hi format +flevel .DA #0 current file level +bubit .DA #0 backup bit disable, setfileinfo only +spare1 .DA #0 used to save acc +newpfxptr .DA #0 appletalk alternate prefix ptr +machidbyte .DA #0 machine ID byte +rommap .DA #0 slot ROM bit map +preflag .DA #0 prefix active flag +mliact .DA #0 MLI active flag +mliretn .DA 0 last MLI call return address +mlix .DA #0 MLI X register savearea +mliy .DA #0 MLI Y register savearea + +* language card bank switching routines which must reside at $BFA0 because +* workstation software patches this area + +HBFA0 eor $E000 test for rom enable + beq .1 taken if ram enabled + sta RROMBNK2 read ROM + bne .2 always +.1 lda bnkbyt2 for alternate ram + eor $D000 test + beq .2 branch if not alternate ram + lda RRAMWRAMBNK2 else enable alt $D000 +.2 pla return code + rti re-enable interrupts and return + +mlicont sec + ror mliact notify interrupt routines MLI active. + lda $E000 preserve language card/rom orientation + sta bnkbyt1 for proper restoration when mli exits. + lda $D000 + sta bnkbyt2 + lda RRAMWRAMBNK1 force ram card on + lda RRAMWRAMBNK1 with write allowed + jmp XDOS.MLI + +GP.IrqExit lda bankid determine state of ram card (ROM/RAM) + +irqxit0 beq .2 branch if ram card enabled. + bmi .1 branch if alternate $D000 enabled. + + lsr determine if no ram card present. + bcc .3 branch if rom only system. + + lda RROMWRAMBNK2 enable rom + bcs .3 always taken + +.1 lda RRAMWRAMBNK2 enable alternate $D000 +.2 lda #$01 preset bankid for rom. + sta bankid (reset if ram card interrupt) +.3 lda p8areg restore acc + rti exit + +irqent bit RRAMWRAMBNK1 this entry only used when rom + bit RRAMWRAMBNK1 was enabled at time of interrupt. + jmp irqrecev + +bnkbyt1 .DA #0 +bnkbyt2 .DA #0 + .HS 00000000 pad to before $BFFA + .DA #4 gsos compatibility byte ($BFFA) + .DA #0 pad + .DA #0 reserved + .DA #0 version # of running interpreter + .DA #0 preserved for System Utilities +kversion .HS 23 represents release 2.0.3 +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.GP +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.IRQ.txt b/ProDOS.FX/ProDOS.S.IRQ.txt new file mode 100644 index 00000000..6071ef4c --- /dev/null +++ b/ProDOS.FX/ProDOS.S.IRQ.txt @@ -0,0 +1,71 @@ +NEW + AUTO 3,1 +*-------------------------------------- +* this routine handles interrupts and is coded to reach 'lreset' precisely at +* address $FFCB (ROM rts opcode) for rom switching to function. +* $2D9B-2DFF moved to $FF9B-FFFF +*-------------------------------------- +lanirq pha + lda accsav + sta oldacc + pla + sta accsav + pla get status register from stack + pha and put it back. + and #$10 is it a break or interrupt? + bne H2DC2 branch if break. + + lda $D000 get ram bankid (LC1 = $D8, LC2=$EE) + eor #$D8 is the system active? ($D8) + beq sysactv branch if it is + lda #$FF +sysactv sta bankid + sta afbank + lda /aftirq setup return address + pha + lda #aftirq + pha + lda #$04 status reg with interrupt flag set + pha +H2DC2 lda /romirq setup ROM re-entry + pha + lda #romirq + pha +gorom sta RROMBNK2 hits ROM rts at $FFCB + +* 'lreset' address must = $FFCB for rom switch i/o to work + +lreset lda rreset+1 + pha + lda rreset + pha + jmp gorom + +rreset .DA resetv-1 rts to resetv + +fix45 sta p8areg A register savearea + lda oldacc + sta accsav + lda RRAMWRAMBNK1 read/write RAM bank 1 + lda RRAMWRAMBNK1 + lda afbank + jmp irqxit0 + +stypfx sty newpfxptr fix appletalk PFI bug + sty preflag prefix flag + rts + +stapfx sta newpfxptr + sta preflag + rts + +* these 3 vectors hard-coded into processor + + .DA nmivect nmi handler + .DA lreset reset handler +irqv .DA lanirq irq handler +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.IRQ +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.LDR.A.txt b/ProDOS.FX/ProDOS.S.LDR.A.txt new file mode 100644 index 00000000..b0a50661 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.LDR.A.txt @@ -0,0 +1,742 @@ +NEW + AUTO 3,1 +*-------------------------------------- +H2000 jmp prostart + jmp atalkset appletalk setup for network boot + jmp p16start GQuit setup for gs/os + +LDR.MSG.AppleII .AS -"Apple II" +LDR.MSG.ProDOS .AS -"ProDOS 8 V2.0.3 " + .AS -"06-May-93" +H202F .AS -"A2osX Custom" +LDR.MSG.Copyright + .AS -"Copyright Apple Computer, Inc., 1983-93" +LDR.MSG.Reserved + .AS -"All Rights Reserved." + +p16start inc setuprts set = 2 for GQuit rts +atalkset inc setuprts set = 1 for appletalk rts +prostart lda unitnum + sta LDR.MLIONLINE.P+1 + jsr LDR.Splash + +* test for at least a 65c02 + + sed + lda #$99 a negative # + clc + adc #$01 +1 in decimal = 0 (positive) + cld + bmi m48k if 6502 because will not clear N flag + +* machine at least an m65c02 + + lda #$01 patch for the gs rom + trb statereg to force off intcxrom + ldx #H232B yx=232B location table + ldy /H232B + jsr reloc move interpreter loader to $800 + bcs m48k error + +* test for at least 64k + + ldy #$00 + lda #$FF + sta kversion at least 48k ? + eor kversion + sec + bne m48k if not. + + sta kversion try again to be sure + lda kversion + bne m48k still not. + + lda RROMBNK2 read ROM + jsr whchrom get preliminary system config + bcs m48k machine too small + lda idapple + and #$20 + bne m64k if at least 64k //+. +m48k jmp H22EB need enhanced IIe + +* we have 64k, now determine model: //e , iic, or Cortland (//gs) + +m64k ldx #H2367 yx=2367 relocation table + ldy /H2367 + jsr reloc + lda kversion + sta xdosver save current version for dir use +H20CE bcc H20D3 + jmp relocerr +H20D3 lda RROMBNK2 read ROM + ldx version ROM id byte + cpx #$06 + bne H211D then it's a //e + lda #$E0 + bit zidbyte another ROM id byte + php + lda idapple + and #$37 + plp + bvc set3 if //c or //x + bmi set7 if //e + +set3 php + ora #$08 + plp + bpl mach2 if //c + ora #$40 + bpl H20FD always taken. +mach2 inc cflag //c or later + bvs H20FD +set7 ora #$80 + +H20FD sta idapple + lda RROMBNK2 read ROM + sec + jsr idroutine returns system info + bcs H211D branch if // family + inc cortland it's a Cortland, set loader flag + stz vmode force setvid to reset cursor + jsr setvid reset output to screen + lda setuprts + bne H211D branch if prodos 8 alone + +* running from gs/os shell so zero out os_boot for appletalk + + sta OS_BOOT indicates O/S initially booted. + jsr patch101 patch for gs/os - rev note #101 + +* put dispatcher in bank 2 of language card + +H211D lda LDR.MLIONLINE.P+1 place boot devnum in globals + sta LDR.MLIREADBLOCK.P+1 + sta devnum last device used + jsr devsrch finish setting up globals + lda LDR.MLIREADBLOCK.P+1 + sta devnum + jsr lc1in switch in language card bank 1. + ldx #rlclk64 set up clock + ldy /rlclk64 + jsr reloc + +H2139 bcs H20CE + lda #calldisp + sta jspare+1 P8 system death vector + lda /calldisp + sta jspare+2 + lda RRAMWRAMBNK2 read/write RAM bank 2 + lda RRAMWRAMBNK2 + ldx #altdsptbl GQuit dispatcher + ldy /altdsptbl + lda setuprts + cmp #$02 is this a GQuit setup? + beq H216E taken to use GQuit dispatcher. + ldx #newquitbl else, use Bird's Better Bye + ldy /newquitbl if correct machine. + lda machid machine ID byte + bit #$00 //c ? + bne H216E if yes, can use. + and #$C2 + cmp #$82 //e with 80 col card ? + beq H216E if yes, can use. + ldx #dsp64 else, use original quit code + ldy /dsp64 + inc newquitflag using old quit code so set flag + +H216E jsr reloc + lda #$EE byte to distinguish LC bank 2 + sta $D000 + jsr lc1in switch in LC bank 1 + bcs H2139 + +* test for 128k needed to install ram disk + + lda machid machine ID byte + and #$30 + eor #$30 + bne noramdsk if < 128k + ldx #$FF + php save interrupt status + pla in acc. + sei no interrupts. + sta SETALTZP use alt zero page/stack + stx auxsp init aux sp to $FF + sta CLRALTZP use main zero page/stack + pha restore interrupt status + plp + sta CLRC3ROM enable internal slot 3 ROM + jsr RAMDRV.Install + +* check interrupt vector to determine ROM version + +noramdsk lda RROMWRAMBNK2 read ROM/write RAM bank 2 + ldy irqv interrupt vector + ldx irqv+1 x = high byte + jsr lc1in set language card bank 1 to r/w + cpx #$D0 is it > $D000 (old roms) + lda #$00 + bcs H21C5 branch if old roms + + sta SETALTZP use alt zero page/stack + lda #$FF set aux sp = $FF + sta auxsp + stx irqv+1 interrupt vector + sty irqv save irq vector in aux lc + sta CLRALTZP use main zero page/stack + stx irqv+1 save irq vector in main lc + sty irqv + lda #$01 +H21C5 sta irqflag 1 = new roms + stz cortflag assume not Cortland system + lda cortland running on a Cortland ? + beq H21D5 branch if not. + inc cortflag yes it's Cortland + bra docard + +* check for a rom in slot 3. if no rom, use internal $C300 firmware + +H21D5 sta CLRC3ROM enable internal slot 3 ROM + lda rommap slot ROM bit map + and #$08 mask all but slot 3 + bne isromin3 taken if rom in slot 3 + bra H2247 else continue booting + +* found a rom in slot 3. is it an external, identifiable 80 col card +* with interrupt routines? if so, enable it else use internal $C300 firmware. + +isromin3 sta SETC3ROM enable slot 3 rom + lda $C305 check card id bytes + cmp #$38 + bne hitswtch not terminal card + lda $C307 + cmp #$18 + bne hitswtch + lda $C30B + cmp #$01 + bne hitswtch + lda $C30C is it an apple 80 col compatible card? + and #$F0 + cmp #$80 + bne hitswtch if not. + lda machid machine ID byte + and #$C8 + cmp #$C0 is it a //+ ? + beq docard yes + lda $C3FA + cmp #$2C does card have an interrupt handler? + beq docard yes + +hitswtch sta CLRC3ROM enable internal $C300 firmware + +* verify that the card in aux slot is actually present + + sta SET80STORE enable 80-col store + sta SETPAGE2 switch in text page 2 + lda #$EE + sta txtp2 + asl + asl txtp2 + cmp txtp2 + bne H2230 + lsr + lsr txtp2 + cmp txtp2 + +H2230 sta CLRPAGE2 main memory + sta CLR80STORE disable 80-col store + beq docard branch if card is there + lda machid machine ID byte + and #$FD clear 80-col bit 2 (no card) + bne H2244 always +docard lda machid + ora #$02 turn bit 2 on (80-col card is present) +H2244 sta machid +H2247 lda cortland are we running on a //gs ? + beq H225D if not. + lda #$4C enable clock routine by putting a jmp + sta clockv in front of clock vector + ldx #cortclock yx = relocation table + ldy /cortclock for cortland clock driver + jsr reloc + lda #$01 set bit 0 = clock present + tsb machid +H225D lda setuprts get setup entry point flag + beq H2267 taken if normal boot. + lda RROMBNK2 read ROM + rts return to caller at setup entry point. +setuprts .DA #$00 0 = normal boot, <>0 = return + +* set prefix to boot device + +H2267 jsr MLI + .DA #MLIONLINE + .DA LDR.MLIONLINE.P + bcs relocerr + + lda pbuf+1 get volume name length. + and #$0F strip devnum + beq relocerr + inc add 1 for leading '/' + sta pbuf save prefix length. + lda #'/' place leading '/' in prefix buffer + sta pbuf+1 + + jsr MLI + .DA #MLISETPREFIX + .DA LDR.MLISETPREFIX.P + bcs relocerr + tax =0 + stx dst + ldy #$02 read directory into buffer + lda /DirBlkBuf +H228E sta dst+1 + sta LDR.MLIREADBLOCK.P+3 + sty LDR.MLIREADBLOCK.P+4 + stx LDR.MLIREADBLOCK.P+5 + jsr MLI + .DA #MLIREADBLOCK + .DA LDR.MLIREADBLOCK.P + bcs relocerr + ldy #$03 get next block# from link + lda (dst),y + tax + dey + ora (dst),y if both bytes are the same + beq H22B7 then no more blocks of directory. + lda (dst),y + tay + lda dst+1 + clc + adc #$02 add $200 to buffer pointer + cmp /dbuf+$800 until it points past end of buffer. + bcc H228E if ok, read next block. + +H22B7 jmp $800 jmp to "load interpreter" code + +* relocation/configuration error + +relocerr sta RROMBNK2 read ROM + jsr home + ldy #$1D + +.1 lda LDR.MSG.LdrErr,y + sta vline12+4,y + dey + bpl .1 + + bmi * + +LDR.MSG.LdrErr .AS -"Relocation/Configuration Error" + +H22EB ldy #$23 +.1 lda LDR.MSG.EnhErr,y + sta vline14+2,y + dey + bpl .1 + bmi * + +LDR.MSG.EnhErr .AS -"REQUIRES ENHANCED APPLE IIE OR LATER" + +LDR.MLIONLINE.P .DA #2 + .DA #$60 + .DA pbuf+1 +LDR.MLISETPREFIX.P + .DA #1 + .DA pbuf +LDR.MLIREADBLOCK.P + .DA #3 + .DA #0 unit number + .DA 0 2 byte data buffer + .DA 0 2 byte block number + +cortland .BS 1 cortland loader flag (1 = Cortland) +newquitflag .BS 1 1 = old quit code + +H232B .DA #1 move interpreter loader code + .DA $800 destination address + .DA licode.end-licode length to move + .DA LOADINT source address + .DA #$01 move $3F0 vectors + .DA p3vect destination + .DA $0010 16 bytes to move + .DA H257B source + .DA #$01 + .DA lookptr destination address + .DA $0002 length to move + .DA dst source + .DA #$01 move 128k test to zero page + .DA tst128 destination + .DA LDR.Test128.Len length to move + .DA LDR.Test128 source + .HS FF done + +dsp64 .DA #$01 move p8 dispatcher code + .DA displc2 destination + .DA $0300 length (must be <= 3 pages) + .DA SEL0 source + .HS FF done + +newquitbl .DA #$01 move Bird's Bye code + .DA displc2 dest + .DA $0300 length (must be <= 3 pages) + .DA SEL1 source + .HS FF done + +altdsptbl .DA #$01 move GQuit launcher + .DA displc2 destination + .DA $0300 length (must be <= 3 pages) + .DA SEL2 source + .DA #$01 move a copy of GQuit launcher + .DA dispadr to dispadr for gsos + .DA $0300 length (must be <= 3 pages) + .DA SEL2 source + .HS FF done + +* tables for moving 64k version of mli for execution + +H2367 .DA #$01 relocation table. 1=move src to dst + .DA $ff9b destination + .DA $100-$9B length to move + .DA IRQ source + .DA #$01 + .DA MLI dst + .DA $0100 in one page + .DA GP src + .HS 00 0=clear buffers $D700-$DDFF + .DA $D700 start + .DA $0700 len + .DA #$01 + .DA $DE00 dst + .DA $2100 length of mli + .DA XDOS src + .DA #$01 + .DA $D000 + .DA $0700 length of disk ii driver + .DA XRW + .HS FF done + +* move thunderclock + +rlclk64 .DA #$01 relocation table. 1=move src to dst + .DA $D742 destination + .DA TCLK.END-TCLK.START length of thunderclock driver + .DA TCLK source + + .DA #$04 4=relocate and move program + .DA TCLK.START + .DA TCLK.CEND-TCLK.START + .DA TCLK.START + .HS 00 + .HS C1C1 +clock64 .DA #$00 + .HS FF done + +* move cortland clock + +cortclock .DA #$01 relocation table. 1=move src to dst + .DA $D742 destination + .DA CCLK.END-CCLK.START length of cortland clock driver + .DA CCLK source + .HS FF done + +* load and run appletalk configuration file (atinit) if present +* or continue loading and running .system file + +* loader origin $800 + +LOADINT .PH $800 + +licode jsr MLI check for file 'atinit' + .DA #MLIGETFILEINFO + .DA gfi_list + bcc gfi_ok branch if 'atinit' file found + cmp #$46 file not found? + beq H23DF if so, continue loading interpreter + bne H23E2 +gfi_ok lda gfi_type + cmp #$E2 is 'atinit' correct file type? + bne H23E2 error - wrong file type + jsr MLI open 'atinit' file + .DA #$C8 + .DA atopen + bne H23E2 error + lda #$9F max size = 39.75k ($2000-$BF00) + sta rdlen+1 + stz rdlen + jsr MLI read 'atinit' file to 'sysentry' + .DA #$CA + .DA rdparm + bne H23E2 error - too big + jsr MLI close 'atinit' file + .DA #$CC + .DA clparm + bne H23E2 error + lda RROMBNK2 enable ROM + jsr sysentry execute ATinit +H23DF jmp goloadint execute .system file + +* fatal error + +H23E2 ldx $23F0 BUG: should be ATINIT.ERR +H23E5 lda $23F0,x BUG: should be ATINIT.ERR + sta vline16,x + dex + bne H23E5 + beq * + +ATINIT.ERR .DA #$1A length of message + .AS -"Unable to load ATInit file" +gfi_list .DA #$0A + .DA atinitname + .HS 00 +gfi_type .HS 00000000 + .HS 0000000000000000 + .HS 0000 +atopen .HS 03 + .DA atinitname + .DA iobuf i/o buffer + .HS 01 ref# hard coded since no other files +atinitname .DA #06 length of name + .AS -"atinit" name of appletalk config file +goloadint + lda /dbuf search directory buffer + sta idxl+1 + lda #$04 start 1 entry past header + bne H2434 always. +H2432 lda idxl calc next entry position +H2434 clc + adc dbuf+35 inc to next entry address + sta idxl + bcs H2451 branch if page cross. + adc dbuf+35 test for end of block. + bcc H2453 branch if not page cross + lda idxl+1 + lsr end of block? + bcc H2453 no. + cmp #$09 end of directory? + bne H244D no. + jmp nointrp no interpreter, go quit. +H244D lda #$04 reset index to 1st entry in next block. + sta idxl +H2451 inc idxl+1 inc to next page. +H2453 ldy #$10 check file type. + lda #$FF must be a prodos sys file + eor (idxl),y + bne H2432 if not sys. + tay see if active + lda (idxl),y + beq H2432 if deleted file. + and #$0F strip file 'kind'. + sta pbuf save length of name. + cmp #$08 must be at least 'x.system' + bcc H2432 else, ignore it. + tay compare last 7 chars for '.system' + ldx #$06 +H246C lda (idxl),y + eor iterp,x + asl + bne H2432 branch if something else + dey + dex + bpl H246C + ldy #$00 +H247A iny + lda (idxl),y + sta pbuf,y + ora #$80 msb on so can be displayed if error + sta iomess+$11,y + cpy pbuf + bne H247A + lda #$A0 space after name + sta iomess+$12,y + tya error message length + adc #$13 (carry set) + sta ierlen + jsr MLI open interpreter file + .DA #$C8 + .DA opparm + bne badlod + jsr MLI get eof (length of file) + .DA #$D1 + .DA efparm + bne badlod + lda eof+2 + bne toolong + lda eof+1 + cmp #$9F max size = 39.75k ($2000-$BF00) + bcs toolong + sta rdlen+1 + lda eof + sta rdlen (read entire file) + jsr MLI read interpreter file + .DA #$CA + .DA rdparm + beq H24C8 go close if successfully read. + cmp #$56 memory conflict? + beq toolong then too large + bne badlod else, unable to load. +H24C8 jsr MLI close interpreter file + .DA #$CC + .DA clparm + bne badlod hopefully never taken + +* if booting on a //c then see if esc is in keyboard buffer +* and clear it. it may have been pressed to shift speed +* of accelerator chip + + lda cflag + beq H24DF taken if not booting on a //c + lda kbd else, check for keypress + cmp #$9B escape? + bne H24DF if not. + sta KBDSTROBE clear keyboard +H24DF lda RROMBNK2 enable ROM + jmp sysentry go run interpreter + +cflag .HS 00 set if a //c. + +nointrp jsr MLI no interpreter found,so quit. + .DA #$65 + .DA quitparm + +badlod ldy ierlen center the error message + lda #$27 + sec + sbc ierlen + lsr + adc ierlen + tax +H24FA lda iomess,y + sta vline16,x + dex + dey + bpl H24FA + bmi H2511 +toolong ldy #$1E +H2508 lda lgmess,y + sta vline16+5,y + dey + bpl H2508 +H2511 bmi H2511 +lgmess .AS -"** System program too large **" +iomess .AS -"** Unable to load" + .AS -" X.System *********" +ierlen .HS 00 +opparm .HS 03 + .DA pbuf + .DA iobuf + .HS 01 +efparm .HS 02 + .DA #01 +eof .HS 000000 length of file. +rdparm .HS 04 + .HS 01 + .DA sysentry +rdlen .HS 0000 + .HS 0000 +clparm .HS 01 + .HS 00 +quitparm .HS 04 + .HS 00 + .HS 0000 + .HS 00 + .HS 0000 +iterp .AS -".SYSTEM" interpreter suffix that is required + +licode.end .EP + +* 16 bytes moved to $03F0 vectors + +H257B .DA breakv + .DA oldrst + .DA #$5A powerup byte + jmp oldrst '&' vector + jmp oldrst ctrl-y vector + .HS 004000 + .DA irqent global page interrupt vector +lc1in lda RRAMWRAMBNK1 read/write language card RAM bank 1 + lda RRAMWRAMBNK1 + rts + +* determine which system model and save in machine id (idapple) + +whchrom stz idapple assume standard apple // + ldx version check hardware id + cpx #$38 is it apple // (autostart rom)? + beq H25BE if yes + lda #$80 + cpx #$06 apple //e? + beq H25BC if yes + lda #$40 + cpx #$EA apple //+? + bne H25B6 it not, then machine is unknown. + ldx $FB1E apple /// in emulation? + cpx #$AD + beq H25BC taken if apple //+. + lda #$D0 test again for apple /// emulation + cpx #$8A because will only have 48k memory. + bne H25B6 if taken, then machine is unknown. +H25B4 sec apple /// emulation is not allowed + rts because insufficient memory. +H25B6 lda #$02 machine unknown + sta (dst),y + bne H25D9 always. +H25BC sta idapple save machine id + +* check for language card ram + +H25BE jsr lc1in switch in language card bank 1 + lda #$AA + sta $D000 + eor $D000 if LC present, result = 0. + bne H25B4 othewise, insufficient memory. + lsr $D000 check lc again + lda #$55 + eor $D000 + bne H25B4 not sufficent memory. + lda #$20 LC ram is available + ora idapple +H25D9 jmp tst128 jumps to page 0 routine below + +* test for 128k. use page 0 for this routine + +LDR.Test128 sta idapple H25DC-2621 was moved to location tst128 + bpl not128 if already determined < 128k + lda #$EE + sta SETWRITEAUX write to aux mem while on main zp + sta SETREADAUX and read aux mem. + sta dbuf write these locs just to test aux mem + sta $800 1k apart from each other. + lda dbuf + cmp #$EE + bne noaux + asl dbuf may be sparse mem mapping so + asl change value and see what happens. + cmp dbuf + bne noaux branch if not sparse mapping. + cmp $800 + bne H2606 if not sparse. +noaux sec no aux memory available. + bcs H2607 +H2606 clc +H2607 sta CLRWRITEAUX switch back to main memory + sta CLRREADAUX + bcs not128 if < 128k + lda idapple + ora #$30 set id = 128k present + sta idapple +not128 lda lookptr+1 + sec + sbc #$05 + sta lookptr+1 + bcs H2620 + dec lookptr +H2620 clc + rts +LDR.Test128.len .EQ *-LDR.Test128 +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.LDR.A +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.LDR.B.txt b/ProDOS.FX/ProDOS.S.LDR.B.txt new file mode 100644 index 00000000..d5130003 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.LDR.B.txt @@ -0,0 +1,942 @@ +NEW + AUTO 3,1 +*-------------------------------------- +LDR.Splash cld + sta CLR80DISP disable 80 col hardware + sta CLR80STORE disable 80 col store + jsr setnorm set normal text mode + jsr init init text screen + jsr setvid reset output to screen + jsr setkbd reset input to keyboard + jsr home + ldx #$07 +.1 lda LDR.MSG.AppleII,x + sta vline10+16,x + dex + bpl .1 + + ldx #$1D +.2 lda LDR.MSG.ProDOS,x + sta vline12+5,x + dex + bpl .2 + ldx #$0B +.3 lda H202F,x + sta vline14+14,x + dex + bpl .3 + ldx #$26 +.4 lda LDR.MSG.Copyright,x + sta vline23,x + dex + bpl .4 + ldx #$13 +.5 lda LDR.MSG.Reserved,x + sta vline24+10,x + dex + bpl .5 + sec + jsr idroutine returns system info + bcs .8 taken if not a //gs + lda #$80 + trb newvideo video mode select +.8 bit $C000 + bpl .8 + sta $C010 + rts +*-------------------------------------- +* find all disk devices in system slots and set up address +* and device table in prodos global page. if there is a disk +* card in slot 2 then limit the # of devices in slot 5 +* smartport to only 2 +*-------------------------------------- +numdev2 .HS 0000000000000000 8 bytes for smartport call +driveradr .DA 0 +d2idx .DA #0 +diskins2 .DA #0 msb clear if drive in slot 2 + +devsrch stz dst + stz dst+1 + stz idxl + ldx #$FF init to no active devices. + stx numdevs count (-1) active devices. + lda #$0E start disk // area at end of devlist. + sta d2idx + +* check slot 2. if there is a disk card then clear the msb of diskins2. this +* will limit the # of devices in any slot 5 spartport card to 2. + + lda #$C2 + sta idxl+1 check slot 2 + jsr cmpid is there a disk in slot 2 ? + ror diskins2 if so, clear msb else set it. + lda #$C7 search slots from high to low + sta idxl+1 +H26AB jsr cmpid + bcs H270C if no ProDOS device in this slot. + lda (idxl),y check last byte of $Cn rom (y = $ff) + beq diskii branch if 16 sector disk II. + cmp #$FF if = $FF then 13 sector disk II. + bcs H270C ignore if 13 sector boot ROM + sta driveradr else assume it's an intelligent disk. + ldy #$07 check for a smartport device. + lda (idxl),y + bne H26C4 no smartport + jmp smartprt + +H26C4 ldy #$FE + lda (idxl),y get attributes. + and #$03 verify it provides read and status calls. + cmp #$03 + sec assume it's an off-brand disk + bne H270C + jsr setdevid set up the devid byte from attributes + clc + php remember that it's not a disk //. + lsr move # of units (0=1, 1=2) to carry. + lda idxl+1 store hi entry addr (low already done) + bne H26E6 branch always. + +diskii sta devid =0 since disk ii's have null attributes + sec + php remember it's a disk // + lda #RWTS + sta driveradr + lda /RWTS + +H26E6 sta driveradr+1 + jsr installdev install 1 or 2 devices from this slot. + plp get back if it's a disk // (carry). + bcc nxtdsk2 if not disk //. + dex move the list pointer back by 2 devices + dex + stx numdevs count (-1) active devices + dec d2idx increase the disk two index + dec d2idx + ldy d2idx + inx adj since device count starts with $FF. + lda devlist+1,x get entries for disk // + sta devlist,y move then toward the end of the list + lda devlist,x + sta devlist+1,y + dex back to numdevs again +nxtdsk2 clc +H270C jsr sltrom test for ROM in given slot and set flags + dec idxl+1 next lower slot. + lda idxl+1 + and #$07 have all slots been checked ? + bne H26AB no. + +* perform the new device search, mapping unmounted smartport devices +* to empty slots in the device table. + + jsr newmount + +* now copy the disk // list to the end of the regular list. +* start by making the device count include disk //'s + + ldx numdevs current device count - 1 + lda #$0E + sec + sbc d2idx + beq H2747 if there were no disk //'s then done. + clc + adc numdevs sum of disk //'s and others. + sta numdevs + inx move to open space in regular list. + ldy #$0D first disk // entry. +H272F lda devlist,y + pha + lda devlist,x + sta devlist,y + pla + sta devlist,x + inx + dey + sty d2idx use as a temp + cpx d2idx + bcc H272F continue until indexes cross +H2747 ldy #$00 + ldx numdevs now change the device order so that + +H274C lda devlist,x the boot device will have highest + pha priority. + and #$7F strip off high bit + eor devnum for comparison. + asl + bne H275A + pla + iny +H275A dex + bpl H274C + + ldx numdevs now reverse order of search, hi to lo. + tya was boot device found ? + beq H2777 + lda devnum make boot device 1st in search order. + sta devlist,x + dex + bmi H277E branch if only one device. + dey is this a 2 drive device ? + beq H2777 branch if not. + eor #$80 make boot device, drive 2 next. + sta devlist,x + dex + bmi H277E branch if only 1 device, 2 drives. +H2777 pla + sta devlist,x + dex + bpl H2777 +H277E jsr fndtrd save accumulated machine id. + beq H2787 + sta machid machine ID byte + rts +H2787 jmp H25B6 +stadrv ora devid combine with attributes. + ldx numdevs + inx put device # into device list. + sta devlist,x + asl now form drive 2 device number, if any. + rts +sltrom bcc H27F3 branch if disk drive + +* test for clock card + + ldy #$06 + +H2799 lda (idxl),y + cmp dskid,y + bne H27BA no clock + dey + dey + bpl H2799 + + lda idxl+1 transfer hi slot address + sbc #$C1 minus $C1 (default) to relocate + sta clock64 references to clock rom. + lda #$4C enable jump vector in globals. + sta clockv P8 clock vector. + lda idapple mark clock as present. + beq H277E + + ora #$01 + sta idapple xxxxxxx1 = clock present. + bne H27F3 always taken. + +* test for 80 col card + +H27BA ldy #$05 + lda (idxl),y + cmp #$38 + bne H27E4 + ldy #$07 + lda (idxl),y + cmp #$18 + bne H27E4 + ldy #$0B + lda (idxl),y + dec must = 1 + bne H27E4 + iny + lda (idxl),y + and #$F0 mask off low nibble. + cmp #$80 generic for 80-col card. + bne H27E4 + lda idapple + beq H277E + ora #$02 + sta idapple xxxxxx1x = 80 col card. + bne H27F3 always taken. + +* test for any other rom + +H27E4 ldx #$00 + lda (idxl) + cmp #$FF apple /// non-slot? + beq H2801 invalid rom +H27EC cmp (idxl) look for floating bus + bne H2801 no rom + inx + bne H27EC +H27F3 lda idxl+1 mark a bit in slot byte + and #$07 to indicate rom present. + tax + lda sltbit,x + ora rommap mark bit to flag rom present + sta rommap slot ROM bit map +H2801 rts + +* id bytes: evens for clock, odds for disk + +dskid .HS 082028005803703C + +* slot bits + +sltbit .HS 0002040810204080 + +fndtrd clc + ldy sltbit +H2818 lda (lookptr),y + and #$DF + adc sltbit + sta sltbit + rol sltbit + iny + cpy sltbit+3 + bne H2818 + tya + asl + asl + asl + asl + tay + eor sltbit + adc #$0B + bne H283B + lda idapple + rts + +H283B lda #$00 + rts + +installdev php how many drives (carry). + lda idxl+1 get index to global device table + and #$07 for this slot... + asl + tay into y reg. + asl + asl now form device # = slot # + asl in high nibble. + jsr stadrv OR in low nibble, store in dev list. + plp restore # of devices in carry. + ror if 2 drives, then bit 7=1. + bpl H2853 branch if a 1 drive device (e.g. hard drive) + inx else presume that 2nd drive is present. + sta devlist,x active device list. + +H2853 stx numdevs save updated device count. + asl shift # of drives back into carry. + lda driveradr get high address of device driver. + sta drivertbl1,y device driver table 1. + bcc H2862 branch if single drive. + sta drivertbl2,y device driver table 2. + +H2862 lda driveradr+1 + sta drivertbl1+1,y + bcc H286D + sta drivertbl2+1,y + +H286D rts + +* query smartport status to determine # of devices +* and install up to 4 units in table if card is in slot 5 +* otherwise only 2 units. this includes a patch #74 + +smartprt jsr setdevid setup the devid byte from attributes + lda idxl+1 + sta driveradr+1 + lda driveradr + sta pscall+1 modify operand + clc + adc #$03 + sta spvect+1 + lda driveradr+1 + sta spvect+2 + sta pscall+2 modify operand + asl convert $Cn to $n0 + asl + asl + asl + sta unitnum unit number + stz A4L force a prodos status call + stz buf dummy pointer + stz bloknml # of bytes to transfer + stz bloknml+1 + lda #$10 + sta buf+1 dummy pointer should be <> 0 + +* do a prodos status call patched in from above + +pscall jsr $0000 self modifying code + ldy #$FB + lda (idxl),y check device id + and #$02 SCSI? + beq H28B1 no, no need to init Cocoon + sta statunit device = 2 for SCSI + +* initialize SCSI Cocoon to build internal device tables +* and report true # of devices attached + + jsr spvect status of Cocoon + .HS 00 + .DA spcparms ignore any errors. +H28B1 stz statunit set unit# = 0 + jsr spvect call to get the device count. + .HS 00 this is a status call + .DA spcparms + lda numdev2 + beq donesp no devices, so done. + cmp #$02 carry set if 2,3,4 + jsr installdev do the 1st and 2nd device if exists. + lda idxl+1 + cmp #$C5 + bne donesp if not slot 5 + +* for slot 5, if there is a disk card in slot 2 +* then only install 2 devices otherwise map +* extra devices as slot 2 + + bit diskins2 disk in slot 2 ? + bpl donesp yes - so done + lda numdev2 + cmp #$03 carry set if 3,4,... + bcc donesp + cmp #$04 carry set if 4,5,6,... + lda #$C2 map extra devices as slot 2 + sta idxl+1 + jsr installdev + lda #$C5 + sta idxl+1 +donesp jmp nxtdsk2 it's a disk device. +setdevid ldy #$FE check attributes byte. +H28E8 lda (idxl),y + lsr move hi nibble to lo nibble for + lsr device table entries. + lsr + lsr + sta devid + rts + +* check unknown card to see if disk id = $Cn00:nn 20 nn 00 nn 03 + +cmpid lda CLRC8ROM switch out $C8 ROMs + ldy #$05 +H28F6 lda (idxl),y compare id bytes + cmp dskid,y + sec set if no disk card + bne H2903 + dey + dey + bpl H28F6 loop until all 4 id bytes match. + clc clear if disk card +H2903 rts + +* smartport call parameters + +spcparms .DA #$03 # of parms +statunit .DA #$00 unit number (code for smartport stat) + .DA numdev2 + .DA #00 status code (0 = general status) + +* indexes into driver table + +driveridx .DA #$06 s3, d1 + .DA #$1E s7, d2 + .DA #$0E s7, d1 + .DA #$1C s6, d2 + .DA #$0C s6, d1 + .DA #$1A s5, d2 + .DA #$0A s5, d1 + .DA #$14 s2, d2 + .DA #$04 s2, d1 + .DA #$12 s1, d2 + .DA #$02 s1, d1 + .DA #$18 s4, d2 + .DA #$08 s4, d1 + +* self modifying jmp = smartport entry address + +spvect jmp $0000 self modifying + +newmount stz idxl + lda #$C7 start with slot 7 ($C700) + sta idxl+1 + +H291F jsr H29EB is there a smartport device here? + bcs H2974 no, next device. + + ldy #$FF get smartport address. + lda (idxl),y + clc + adc #$03 add 3 for smartport call + sta spvect+1 + lda idxl+1 + sta spvect+2 + dey + jsr H28E8 set up device attributes + stz statunit + jsr spvect do a status call on smartport itself + .HS 00 + .DA spcparms + lda numdev2 # of devices on smartport + cmp #$03 + bcc H2974 only 2 devices,skip to next one. + inc add 1 for comparisons. + sta driveradr # of devices + 1. + lda #$03 start at unit #3 (non-slot 5) + ldx spvect+2 + cpx #$C5 is this slot 5? + bne H295B no, start at 3. + bit diskins2 disk controller in slot 2? + bpl H295B yes, so allow remapping of s5 devices + lda #$05 else start looking at unit #5 + +* find block devices on this smartport + +H295B cmp driveradr have we done all units in this slot? + bcs H2974 yes, skip to next slot. + sta statunit store the unit#. + jsr spvect do status call + .HS 00 + .DA spcparms + lda numdev2 is this a block device? + bmi mount yes, so mount it. + +H296E lda statunit go check the next unit# + inc + bra H295B +H2974 dec idxl+1 + lda idxl+1 + cmp #$C0 searched down to slot 0? + bne H291F if not. + rts + +mount ldx #$0C + +H297F ldy driveridx,x + lda drivertbl1,y device driver table 1 + cmp #nodevice + bne H2990 + lda drivertbl1+1,y + cmp /nodevice + beq H2994 +H2990 dex + bpl H297F + rts ran out of space for devices, exit. + +* empty slot found + +H2994 lda idxl+1 + pha + phx + phy + tya which slot is empty? + lsr shift into slot# + and #$07 now 1-7 + ora #$C0 now $C1-$C7 + sta idxl+1 + jsr H29EB smartport interface in this slot? + ply + plx + pla + sta idxl+1 + bcc H2990 yes, can't use to mirror the device. + jsr lc1in write enable LC ram bank 1. + tya divide index by 2 + lsr + tax + lda statunit + sta spunit-1,x store the smartport unit # + lda spvect+1 and entry address. + sta spvectlo-1,x + lda spvect+2 + sta spvecthi-1,x + lda RROMBNK2 write protect lc ram. + inc numdevs + ldx numdevs + tya + lsr + cmp #$08 + bcc nodev2 drive 2 mount + sbc #$08 + ora #$08 +nodev2 asl + asl + asl + asl + ora devid include device attributes + sta devlist,x in the active device list. + lda #remap_sp + sta drivertbl1,y device driver table 1 + lda /remap_sp + sta drivertbl1+1,y + bra H296E + +H29EB jsr cmpid is it a disk controller? + bcs H29F8 no, so return. + sec assume no smartport + ldy #$07 + lda (idxl),y is it a smartport? + bne H29F8 if not. + clc smartport found +H29F8 rts + +* relocation subroutine. on entry, regs yx = address of parameter table +* with the following parameters: +* +* (1) command: 0 = zero destination range +* 1 = move data from src to dst +* 2 = hi addr ref tbl, relocate and move +* 3 = lo/hi addr ref tbl, relocate and move +* 4 = program, relocate and move +* >4 = end of sequence of commands +* (2) destination +* (2) length +* (2) source +* (1) # of address ranges (n) to be relocated +* (n+1) list of low page addresses to be relocated +* (n+1) list of high page addresses to be relocated +* (n+1) list of offset amounts to be added to be added +* if low and high limits have not been met +* +* on exit, carry set if error and yx = addr of error +* with acc = $00 for table error or $FF if illegal opcode + +reloc stx idxl save address of control table + sty idxl+1 +rloop lda (idxl) get relocation command. + cmp #$05 + bcs rlend taken if >= 5 then done. + tax move destination to page 0 + ldy #$01 for indirect access. + lda (idxl),y + sta dst + iny + lda (idxl),y + sta dst+1 + iny + lda (idxl),y also the length (byte count) + sta cnt of the destination area. + iny + lda (idxl),y + sta cnt+1 + bmi rlerr branch if >= 32k. + txa is it a request to zero destination? + beq zero if yes. + iny + lda (idxl),y get source address. + sta src used for move. + sta cde used for relocation + iny + clc + adc cnt add length to get final address + sta ecde + lda (idxl),y + sta src+1 + sta cde+1 + adc cnt+1 + sta ecde+1 + dex test for 'move' command + beq H2AA3 branch if move only (no relocation) + stx wsize save element size (1,2,3) + iny + lda (idxl),y get # of ranges that are valid + sta sgcnt relocation target addresses. + tax separate serial range groups into tbls +H2A42 iny + lda (idxl),y transfer low limits to 'limlo' table + sta limlo,x + dex + bpl H2A42 + ldx sgcnt # of ranges +H2A4E iny + lda (idxl),y transfer high limits to 'limhi' table + sta limhi,x + dex + bpl H2A4E + ldx sgcnt # of ranges +H2A5A iny + lda (idxl),y transfer offsets to 'ofset' table + sta ofset,x + dex + bpl H2A5A + jsr adjtbl adj index pointer to next entry. + ldx wsize test for machine code relocation + cpx #$03 + beq rlcode branch if program relocation + jsr reladr otherwise, relocate addresses in +H2A70 jsr moveSrcDst tables then move to destination. + bra rloop do next table +rlend clc + rts +rlerr jmp tblerr +rlcode jsr rlprog relocate machine code refs + bra H2A70 + +* fill destination range with 0's + +zero jsr adjtbl adj table pointer to next entry. + lda #$00 + ldy cnt+1 is it at least 1 page? + beq H2A94 branch if not. + tay +H2A89 sta (dst),y + iny + bne H2A89 + inc dst+1 next page + dec cnt+1 + bne H2A89 if more pages to clear. +H2A94 ldy cnt any bytes left to 0? + beq H2AA0 if not. + tay +H2A99 sta (dst),y zero out remainder + iny + cpy cnt + bcc H2A99 +H2AA0 jmp rloop +H2AA3 jsr adjtbl + bra H2A70 +adjtbl tya add previous table length to + sec get next entry position in table + adc idxl + sta idxl + bcc H2AB2 + inc idxl+1 +H2AB2 rts +moveSrcDst lda src+1 is move up, down or not at all? + cmp dst+1 + bcc movup + bne movdn + lda src + cmp dst + bcc movup + bne movdn + rts no move. +movup ldy cnt+1 calc highest page to move up + tya and adj src and dst. + clc + adc src+1 + sta src+1 + tya + clc + adc dst+1 + sta dst+1 + ldy cnt move partial page 1st. + beq H2ADE taken if no partial pages +H2AD6 dey + lda (src),y + sta (dst),y + tya end of page transfer? + bne H2AD6 no +H2ADE dec dst+1 + dec src+1 + dec cnt+1 done with all pages? + bpl H2AD6 no + rts +movdn ldy #$00 + lda cnt+1 partial page move only? + beq H2AFC taken if < 1 page to move +H2AED lda (src),y + sta (dst),y + iny + bne H2AED + inc dst+1 next page + inc src+1 + dec cnt+1 more pages? + bne H2AED if more. +H2AFC lda cnt move partial page. + beq H2B09 if no more to move +H2B00 lda (src),y + sta (dst),y + iny + cpy cnt + bne H2B00 +H2B09 rts + +* relocate addresses + +reladr ldy wsize 1 or 2 byte reference + dey + lda (cde),y + jsr adjadr relocate reference. + lda wsize update and test code pointer. + jsr adjcde + bcc reladr if more to do + rts +rlprog ldy #$00 get next opcode + lda (cde),y + jsr oplen determine if a 3 byte instruction. + beq rperr branch if not an opcode + cmp #$03 + bne H2B30 + ldy #$02 + jsr adjadr relocate address + lda #$03 +H2B30 jsr adjcde update and test if done. + bcc rlprog if more to do + rts +rperr pla + pla + ldx cde bad code address in y,x + ldy cde+1 + lda #$FF indicates bad opcode + sec + rts +tblerr ldx idxl bad table address in y,x + ldy idxl+1 + lda #$00 indicates input table error + sec + rts +adjadr lda (cde),y get page address and + ldx sgcnt test against limits. +H2B4D cmp limlo,x is it >= low? + bcc H2B59 if not. + cmp limhi,x is it <= high? + bcc H2B5D branch if it is + beq H2B5D +H2B59 dex try next limit set + bpl H2B4D + rts return w/o adjustment. +H2B5D clc add offset to form relocated + adc ofset,x page address and replace + sta (cde),y old address with result. + rts +adjcde clc update code pointer + adc cde + ldy cde+1 + bcc H2B6C branch if not page cross + iny otherwise, update page#. +H2B6C cpy ecde+1 has all code/data been processed? + bcc H2B72 if not. + cmp ecde +H2B72 sta cde save updated values. + sty cde+1 + rts return result (carry set = done). +oplen pha form index to tbl & which 2-bit group. + and #$03 low 2 bits specify group + tay + pla + lsr upper 6 bits specify byte in table + lsr + tax + lda opcodln,x +nxgroup dey is opcode len in lowest 2 bits of acc? + bmi H2B89 branch if it is + lsr shift to next group. + lsr (if length = 0 then error) + bne nxgroup + +H2B89 and #$03 + rts if z-set then error + +* relocation table contains length of each opcode in 2-bit groups + +opcodln .HS 0928193C0A280D3C + .HS 0B2A193F0A280D3C + .HS 0928193F0A280D3C + .HS 0928193F0A280D3C + .HS 082A113F0A2A1D0C + .HS 2A2A193F0A2A1D3F + .HS 0A2A193F0A280D3C + .HS 0A2A193F0A280D3C + +wsize .HS 00 +sgcnt .HS 00 +limlo .HS 0000000000000000 +limhi .HS 0000000000000000 +ofset .HS 0000000000000000 + +* patch to gsos vectors so error is returned for os calls - rev note #101 + +patch101 php + sei disable interrupts + clc + xce full native mode + >LONGMX + phb save DBR + pha + pha + pea $0000 length of patch + pea $0010 0000/0010 = 16 bytes + pea $3101 user id for prodos 8 + pea $8018 attributes (locked/nospec/nocross) + pha + pha + >IIGS NewHandle + lda $01,s retrieve handle + tax + lda $03,s + tay + pea $0000 copy the code into the handle + pea L2C4D + phy + phx + pea $0000 length of patch = 0000/0010 + pea $0010 + >IIGS PtrToHand + plx low word of handle + plb set DBR to handle's bank + lda >1,x get upper 16 bits of 24 bit address + tay save in y + lda >0,x get low 8 bits of address + and ##$00FF clear high byte + xba put address in high byte + ora ##$005C include JML opcode + sta GSOS2 store in gsos vectors + clc + adc ##$000B + sta GSOS + tya store upper 16 bits too + sta GSOS2+2 + adc ##$0000 adj for possible page crossing + sta GSOS+2 + plb remove garbage byte from stack + plb restore DBR. + sec + xce back to emulation mode + plp + rts + +* copy of the code that goes in the handle + +L2C4D lda 1,s + sta 7,s + lda 2,s + sta 8,s + pla + pla + pla + lda ##$00FF #NoOS + sec + rtl + + .BS $2C80-* + +RAMDRV.Install ldy #$99 move $9A bytesfrom lcsrc to lcdest. + +.1 lda RAM,y transfer main bank portion of driver + sta RAMDRV,y dey + cpy #$FF + bne .1 + ldx #RAMX set up to move aux portion of driver + stx A1L + dex + stx A2L + ldx /RAMX + stx A1L+1 + inx + stx A2L+1 + lda #RAMXDRV + sta A4L + lda /RAMXDRV RAMX to RAMXDRV + sta A4L+1 + sec irection = to aux bank. + jsr auxmove move aux bank portion of driver. + lda #RAMDRV put driver address into + sta drivertbl2+6 slot 3, drive 2. + lda /RAMDRV + sta drivertbl2+7 + inc numdevs count (-1) active devices + ldx numdevs + lda #$BF unit num of /RAM + sta devlist,x + rts + +RAM_1_END .EQ * end of /RAM installer + .BS $2D00-* pad 0's to page boundary + + +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.LDR.B +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.RAM.txt b/ProDOS.FX/ProDOS.S.RAM.txt new file mode 100644 index 00000000..05145996 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.RAM.txt @@ -0,0 +1,88 @@ +NEW + AUTO 3,1 +* object code = ram_2 +* /RAM driver (main bank portion) +* origin = $FF00 + +RAMDRV cld no decimal. + ldx #$0B save 13 bytes of parms +.1 lda A1L,x + sta a1l1,x + dex + bpl .1 + ldx #$01 +.2 lda passit,x save xfer vectors + sta sp1,x + dex + bpl .2 + lda A4L get command. + beq stat 0 = status + cmp #$04 check for command too high. + bcs ioerr if it is, i/o error + eor #$03 + sta A4L 0=format, 2=read, 1=write + beq format + ldy bloknml+1 check for large block number. + bne ioerr too big. + lda bloknml block # + bmi ioerr largest block number is $7F + +* at this point, control is passed to the code in the alternate 64k. +* it it used for read, write and format. after the request is completed, +* control is passed back to 'noerr'. + +format lda #RAMXDRV card entry point + sta passit + lda /RAMXDRV +gocard sta passit+1 also used by 'mainwrt' + sec direction ram -> card + clv start with original zero page + jmp xfer transfer control +ioerr lda #$27 + bne H2D41 + lda #$2B write protect error. +H2D41 sec flags error + bcs H2D47 +noerr .EQ * +stat lda #$00 + clc +H2D47 php save status + pha and error code. + ldx #$0B restore 13 byes of parms +H2D4B lda a1l1,x + sta A1L,x + dex + bpl H2D4B + lda sp1 restore xfer parms. + bit $6060 addr $FF58 must = rts ($60) as in ROM + sta passit + lda sp1+1 + sta passit+1 + pla restore error code + plp and status. + rts +mainwrt sta SETWRITEAUX write to alt 48K + ldy #$00 +H2D6A lda (A1L),y pointers set in card by 'setptr' + sta (A4L),y + lda (A2L),y + sta (A3L),y + dey + bne H2D6A + sta CLRWRITEAUX write to main 48K. + lda #donewrt done writing card + sta passit + lda /donewrt + jmp gocard +sp1 .HS 0000 +a1l1 .BS 13 13 bytes of storage + +* end of obj ram_2 + +RAMDRV.END .EQ * + .BS $FF9B-* fill to lanirq ($FF9B see note below) +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.RAM +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.RAMX.txt b/ProDOS.FX/ProDOS.S.RAMX.txt new file mode 100644 index 00000000..1d47d469 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.RAMX.txt @@ -0,0 +1,322 @@ +NEW + AUTO 3,1 +* object code = ram_0 +* /RAM driver (aux bank portion) +* this code is packed into $200 length with no room for expansion !! +* (see note at end of this obj) + +* after the main /RAM routine has determined that the command is ok and the +* block to be read/written is within range, it transfers control to this +* aux /RAM routine which remaps the block requested as follows: +* request blocks 0,1: invalid +* 2: returns VDIR (card block 3) +* 3: returns BITMAP (synthesized) +* 4: returns card block 0 +* $05-$5F: returns card blocks $05-$5F +* $60-$67: returns blocks $68-$7F in bank 1 of language card +* $68-$7F: returns blocks $68-$7F in bank 2 of language card + +H5100 lda RD80STORE read 80 store + pha save for later + sta CLR80STORE turn off 80 store + ldx #$04 move the parameters for use: +L5109 lda A4L,x cmd, unit, bufptr and block (lo) + sta tcmd,x -> tcmd, tunit, R2L, R2H, R01 + dex + bpl L5109 + and formatflg format the volume first time + bne L514F thru, or when requested. + ldx bloknml save R01 during format. + lda /vblock1 block to be cleared. + jsr clrbuf1 clears all buffers. + ldy #$03 format volume in 2 chunks. +L511F lda VDIR,y + sta vblock1+4,y + dey + bpl L511F + lda #$FE set last block as unusable + sta BITMAP+15 to protect vectors. + tya set bitmap bits to $FF. + ldy #$0E 15 bytes to set +L5130 sta BITMAP,y + dey + bne L5130 + sty BITMAP first byte = 0. + ldy #$07 do other chunk +L513B lda access,y + sta vblock1+34,y + dey + bpl L513B + lda formatflg if 0, set to $FF + bne L51AA else exitcard. + sty formatflg y = $FF, won't format next time. + stx R01 restore R01 + +* use the requested block number to determine +* which routine performs the transfer + +L514F asl R01 block requested -> page requested. + lda R01 get page requested. + cmp #$BF in language card ? + bcs L5163 yes, do it. + cmp #$06 bitmap ? + bne L5160 + jmp tbmap yes, transfer bitmap +L5160 jmp treg else normal transfer. + +* when a block between $60 and $7F is requested, it must be spirited into/from +* the language card area of the 64k card. this requires a 2 stage move: +* into the temp buffer and then to it's real destination. + +L5163 tax save R1 for later. + jsr setptr get direction + php and save it. + bcs L51B8 if it's a write. +lcrd txa get R1 back + cmp #$CF which bank is it in ? + bcs L5173 in main bank. + ora #$10 in secondary bank. + bne L5179 branch always. +L5173 sta RRAMWRAMBNK2 turn on main $D000 + sta RRAMWRAMBNK2 +L5179 sta R01 restore R1. + lda R2H save R2 for later + pha + ldx R2L + sta SETALTZP use alternate zero page/stack + lda /dbuf set R2 to dbuf + sta R2H + lda #dbuf + sta R2L + jsr setptr set pointers + tay A > 0 from setptr +L5194 lda (A1L),y move A1,A2 to A4,A3 + sta (A4L),y + lda (A2L),y + sta (A3L),y + dey + bne L5194 + sta CLRALTZP use main zero page/stack +L51A2 stx R2L + pla restore R2 + sta R2H + plp get direction. +L51AA bcs L51B5 write, done with move. + sta RRAMWRAMBNK1 switch in MLI part of LC + sta RRAMWRAMBNK1 + jsr blockdo0 read, transfer dbuf to main +L51B5 jmp exitcard +L51B8 jsr blockdo0 transfer main to dbuf. + jmp lcrd transfer dbuf to language card + +* blockdo0 transfers a block between main memory and the 64k card. R1 contains +* the page address of the block in the card; R2 contains the page address of +* the block in main memory. the address in main memory is always in the +* language card, so the language card is always switched in. if cmd is 2, a +* write is done (R2->R1); if cmd is 1, a read is done (R1->R2). + +blockdo0 lda /dbuf set up R1 = dbuf +blockdo1 sta R01 +blockdo jsr setptr set pointers. + bcs L51DB it's a write. + sta CLRWRITEAUX transfer buffer directly to main. + tay 0 left from setptr. +L51CC lda (A1L),y transfer A1,A2 to A4,A3 + sta (A4L),y + lda (A2L),y + sta (A3L),y + dey + bne L51CC + sta SETWRITEAUX back the way it was. +donewrt rts mainwrt returns here + +L51DB lda #mainwrt pointers set up, + sta passit pass control to main ram + lda /mainwrt + jmp ex1 set passit+1 and transfer + +* setptr is used by other routines to set up pointers and dtect read or write + +setptr lda tcmd is it read or write ? + lsr + bcs L5208 taken if write. + lda R2H destination page + sta A4L+1 + sta A3L+1 + lda R2L + sta A4L + sta A3L + lda R01 source page + sta A1L+1 + sta A2L+1 + lda #$00 source page aligned + sta A1L + sta A2L + beq L5223 +L5208 lda R2H source page + sta A1L+1 + sta A2L+1 + lda R2L + sta A1L + sta A2L + lda R01 destination page + sta A4L+1 + sta A3L+1 + lda #$00 destination page aligned + sta A4L + sta A3L +L5223 inc A2L+1 + inc A3L+1 + rts + +* tzip is called if blocks 0,1,4,5 are requested. +* on write it does nothing, on read it returns 0's. + +tzip jsr clrbuf0 fill dbuf with 0's + jsr blockdo transfer the 0's + jmp exitcard and return + +* clrbuf fills the buffer indicated by R01 to 0's. +* should only be called on a read or format. + +clrbuf0 lda /dbuf dbuf is temp buffer. +clrbuf1 sta R01 assign to block. +clrbuf2 jsr setptr set pointers + tay acc = 0 +L523A sta (A1L),y + sta (A2L),y + dey + bne L523A + rts + +* treg maps the requested block into the aux card +* so that 8k data files will be contiguous (the index +* blocks will not be placed within data). + +treg cmp #$04 page 4 = vdir + bne L524A not vdir, continue + lda #$07 else transfer block 7 + bne L5258 +L524A cmp #$0F if any page < $F (block 8) requested, + bcc tzip it is invalid. + ldx #$00 x = # of iterations. + lda bloknml use true block #. + cmp #$5D beyond 8k blocks ? + bcc L525B no, do normal + sbc #$50 else subtract offset +L5258 jmp times2 and multiply by 2 + +* determine which 8k chunk it is in, place in x; +* block offset into chunk goes into y. + +L525B sec + sbc #$08 block=block-6 +L525E cmp #$11 if <=17 then done + bcc L5268 + sbc #$11 else block=block-17. + inx iteration count. + bpl L525E should branch always + brk otherwise crash !!! +L5268 tay remainder in y + +* if remainder is 1 then it's an index block: +* start index blocks at $1000,$2000...$19FF. +* if remainder is 0 then it is first data block +* in 8k chunk. page is 32 + (16 * x). +* otherwise, it is some other data block. +* page is 32 + (16 * x) + (2 * y) + + cpy #$01 is it index block ? + bne L5273 no. + txa index = 2 * (8 + x) + clc + adc #$08 + bne times2 multiply by 2. +L5273 inx iteration + 1. + txa page = 2 * (16 + 8x) + asl + asl + asl + asl + sta R01 + tya get offset into 8k chunk + beq L5281 if 0, no offset + dey else offset = 2 * y + tya +L5281 clc + adc R01 +times2 asl acc = 2 * acc + jsr blockdo1 store in R01 and transfer + jmp exitcard and return + +* when block 3 is requested, the bitmap is returned. the real bitmap is only +* 16 bytes long; the rest of the block is synthesized. the temporary buffer +* at $800 is used to build/read a full size bitmap block. + +tbmap lda /dbuf use temp buffer as block + sta R01 + jsr setptr set pointers, test read/write. + bcs L52A9 branch if it's write. + jsr clrbuf2 + ldy #$0F put real bitmap there +L529B lda BITMAP,y + sta (A1L),y + dey + bpl L529B + jsr blockdo move temp buf to user buf + jmp exitcard +L52A9 jsr blockdo move user buf to temp buf + jsr setptr + ldy #$0F move temp buf to bitmap. +L52B1 lda (A4L),y (pointer set by setptr) + sta BITMAP,y + dey + bpl L52B1 + jmp exitcard + +formatflg .HS 00 not formatted yet +tcmd .HS 00 command + .HS 00 unit (not used) +R2L .HS 00 R2 = user buffer +R2H .HS 00 +R01 .HS 00 page requested +BITMAP .HS 00FFFFFF blocks 0-7 used + .HS FFFFFFFF + .HS FFFFFFFF + .HS FFFFFFFE +VDIR .HS F3 storage type = F, name length = 3 + .AS "RAM" +access .DA #$C3 destroy, rename, read enabled + .HS 27 entry length + .HS 0D + .HS 0000 + .HS 0300 block 3 + .HS 7F 128 blocks + +exitcard lda RRAMWRAMBNK1 restore language card + lda RRAMWRAMBNK1 + pla get 80store + bpl L52EA 80store wasn't on + sta SET80STORE enable 80store +L52EA jmp bypass jump around passit +passit .HS 0000 +bypass lda #noerr set up return to noerr + sta passit + lda /noerr +ex1 sta passit+1 also used by blockwrite + clc transfer card to main + clv use standard zeropage/stack + jmp xfer jmp back from language card. + +* NOTE: the previous section of code MUST NOT use $3FE or $3FF +* since the interrupt vector must go there if aux interrupts +* are to be used. no room for expansion here !! + + .HS 0000 $3FE-$3FF + +* end of obj ram_0 +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.RAMX +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.SEL0.txt b/ProDOS.FX/ProDOS.S.SEL0.txt new file mode 100644 index 00000000..e5e04e9f --- /dev/null +++ b/ProDOS.FX/ProDOS.S.SEL0.txt @@ -0,0 +1,297 @@ +NEW + AUTO 3,1 +* object code = sel_0 +* +* dispatcher 1 - this code org's and operates at 'dispadr' (=$1000) but +* is resident in memory at 'displc2' (=$D100) in the alternate 4k bank +* of the language card. the quit call vectors to a routine high in the +* mli that moves dispatcher 1 down and jumps to it. the move routine +* must remain somewhere between $E000-$F7FF. this routine must be less +* than 3 pages in length. + +SEL0.START lda RROMBNK2 read ROM + sta CLR80DISP disable 80 col hardware + sta CLRALTCHAR normal LC, flashing UC + sta CLR80STORE disable 80 column store + jsr setnorm set normal text mode + jsr init init text screen + jsr setvid reset output to screen + jsr setkbd reset input to keyboard + ldx #$17 clear the memory bitmap + lda #$01 but protect page $BF00. + sta memmap,x P8 memory bitmap + dex + lda #$00 +L5A22 sta memmap,x + dex + bpl L5A22 + lda #$CF protect zero page, stack and + sta memmap $400-$7FF (text screen display) +L5A2D jsr home clear screen + jsr crout position top/left + ldx #dsp1msg0-dsp1msgs + jsr prntmsg 'enter prefix...' + lda #$03 line 3 + sta cv + jsr crout + jsr MLI get prefix + .DA #$C7 + .DA dsp1pfx + ldx pbuf get prefix length + lda #$00 put 0 at end of prefix + sta pbuf+1,x + ldx pbuf get length. + beq L5A5D if no prefix to display. +L5A52 lda pbuf,x display prefix directly to screen + ora #$80 normal text + sta vline5-1,x line 5 + dex + bne L5A52 +L5A5D ldx #$00 + dec cv + jsr crout +getkey jsr rdkey input char with cursor + cmp #$8D cr ? + beq L5ABD yes, accept what is entered. + pha no, save the char. + jsr clreol clear rest of line. + pla get char back + cmp #$9B esc ? + beq L5A2D yes, start over + cmp #$98 ctrl-x ? +L5A76 beq L5A2D then start over + cmp #$89 tab ? + beq badkey + cmp #$FF delete ? + beq L5A84 if yes + cmp #$88 backspace ? + bne L5A91 if not +L5A84 cpx #$00 at column 0 ? + beq L5A8B if so, do nothing + dec ch else move left + dex dec char count +L5A8B jsr clreol clear rest of line + jmp getkey get another char +L5A91 bcs L5A99 +badkey jsr bell output bell for bad key + jmp getkey and get another. +L5A99 cmp #$DB below 'Z' ? + bcc L5A9F if yes + and #$DF else shift to uppercase. +L5A9F cmp #$AE below '.' ? + bcc badkey + cmp #$DB above 'Z' ? + bcs badkey + cmp #$BA below ':' ? + bcc goodkey + cmp #$C1 at or above 'A' ? + bcc badkey +goodkey inx + cpx #$27 more than 39 chars ? + bcs L5A76 then too many, go restart. + sta pbuf,x save it + jsr cout + jmp getkey get another. +L5ABD cpx #$00 prefix length = 0 ? + beq L5AD3 if yes, don't set length. + stx pbuf set prefix length. + jsr MLI call mli to set prefix. + .DA #$C6 + .DA dsp1pfx + bcc L5AD3 if ok, go get filename. + jsr bell if not, ring bell + lda #$00 and try again for prefix. +L5AD1 beq L5A76 +L5AD3 jsr home clear screen for application name. + jsr crout + ldx #disp1msg-dsp1msgs + jsr prntmsg 'enter pathname...' +retryrich lda #$03 line 3 + sta cv + jsr crout + ldx #$00 +loop1 jsr rdkey input char with cursor. + cmp #$9B esc ? + bne L5AF4 if not esc. + lda ch esc pressed in column 0 ? + bne L5AD3 if not, get pathname again. + beq L5AD1 if so, get prefix again. +L5AF4 cmp #$98 ctrl-x ? +L5AF6 beq L5AD3 then cancel and get pathname again. + cmp #$89 tab ? + beq L5B09 not good. + cmp #$FF delete ? + beq L5B04 delete char. + cmp #$88 backspace ? + bne L5B07 +L5B04 jmp delchar delete char. +L5B07 bcs L5B0F if > $88 then char may be acceptable. +L5B09 jsr bell output bell (ctl-G) + jmp loop1 not good. +L5B0F cmp #$8D cr ? + beq L5B3C then done. + cmp #$DB less than 'Z' ? + bcc L5B19 no. + and #$DF make sure it's uppercase. +L5B19 cmp #$AE '.' ? + bcc L5B09 not good if less. + cmp #$DB less than '[' ? + bcs L5B09 not good. + cmp #$BA <= '9' ? + bcc L5B29 then ok. + cmp #$C1 greater than 'A' ? + bcc L5B09 if not, then no good. +L5B29 pha it's good, save it. + jsr clreol clear to end of line + pla + jsr cout print it + inx + cpx #$27 more than 39 chars ? + bcs L5AF6 too long, get pathname again. + sta pbuf,x store it. + jmp loop1 get another char +L5B3C lda #$A0 + jsr cout after cr, blank out the cursor. + stx pbuf put length in front of the name. + jsr MLI get file info for pathname in pbuf + .DA #$C4 + .DA dsp1info + bcc L5B4F if no errors. + jmp dsp1error +L5B4F lda dsp1type + cmp #$FF is it a SYS file ? + beq L5B5B yes. + lda #$01 not SYS file error. + jmp dsp1error +L5B5B lda #$00 it's a system file + sta dsp1cln + jsr MLI close all open files + .DA #$CC + .DA dsp1cls + bcc L5B6B + jmp dsp1error +L5B6B lda dsp1acess check for proper access. + and #$01 is read disabled ? + bne L5B77 no, access ok. + lda #$27 i/o error + jmp dsp1error +L5B77 jsr MLI open the file + .DA #$C8 + .DA dsp1open + bcc L5B82 + jmp dsp1error +L5B82 lda dsp1refn copy the reference number + sta dsp1rdn + sta dsp1eofn + jsr MLI get eof + .DA #$D1 + .DA dsp1eof + bcs dsp1error + lda dsp1eofb+2 3rd of 3 bytes. + beq L5B9C if 0 then ok + lda #$27 else i/o error because + bne dsp1error file is too large. +L5B9C lda dsp1eofb move eof to # of bytes to read. + sta dsp1cnt + lda dsp1eofb+1 + sta dsp1cnt+1 + jsr MLI read the file + .DA #$CA + .DA dsp1read + php save the status. + jsr MLI close the file. + .DA #$CC + .DA dsp1cls + bcc L5BBB +L5BB7 plp get status (it is irrelevant now) + bne dsp1error if close generated an error + plp here if close was ok. +L5BBB bcs L5BB7 error. + jmp sysentry execute system file +delchar lda ch is cursor in column 0 ? + beq L5BD3 yes, ignore it. + dex + lda #$A0 blank out the cursor + jsr cout + dec ch + dec ch point to last char entered + jsr cout and blank it too. + dec ch point to that location. +L5BD3 jmp loop1 get next char. +prntmsg lda dsp1msgs,x + beq L5BE1 + jsr cout + inx + bne prntmsg +L5BE1 rts + +* dispatcher 1 error handler + +dsp1error sta errnum + lda #$0C display error message on line 13 + sta cv + jsr crout + lda errnum + cmp #$01 + bne L5BF5 + ldx #dsp1err1-dsp1msgs not a type 'sys' file + bne L5C0B handled separately. +L5BF5 cmp #$40 syntax error in pathname ? + beq L5C09 + cmp #$44 bad subdirectory path ? + beq L5C09 + cmp #$45 volume not found ? + beq L5C09 + cmp #$46 file not found ? + beq L5C09 + ldx #dsp1err2-dsp1msgs if not the errors above then 'i/o error' + bne L5C0B +L5C09 ldx #dsp1err3-dsp1msgs otherwise display 'file/path not found' +L5C0B jsr prntmsg + jmp retryrich retry for application pathname + +dsp1msgs .EQ * +dsp1msg0 .EQ * + .AS -'ENTER PREFIX (PRESS "RETURN" TO ACCEPT)' + .HS 00 +disp1msg .AS -"ENTER PATHNAME OF NEXT APPLICATION" + .HS 00 +dsp1err1 .DA #$87 + .AS -'NOT A TYPE "SYS" FILE' + .HS 00 +dsp1err2 .DA #$87 + .AS -"I/O ERROR " + .HS 00 +dsp1err3 .DA #$87 + .AS -"FILE/PATH NOT FOUND " + .HS 00 +dsp1info .DA #$0A 10 parameters + .DA pbuf pathname buffer +dsp1acess .HS 00 access +dsp1type .HS 00 file type + .BS 13 the rest are unimportant +dsp1open .HS 03 3 parameters for open + .DA pbuf pathname buffer + .DA fbuf fcb buffer +dsp1refn .HS 00 reference # +dsp1cls .DA #01 1 parameter for close +dsp1cln .HS 00 reference # +dsp1read .HS 04 4 parameters for read +dsp1rdn .HS 00 reference # + .DA sysentry .SYS load address +dsp1cnt .HS 0000 byte count + .HS 0000 +dsp1eof .HS 02 2 parameters +dsp1eofn .HS 00 reference # +dsp1eofb .HS 000000 3 byte eof +dsp1pfx .DA #01 1 parameter + .DA pbuf prefix buffer + + .BS $1300-* fill to page boundary + +* end of obj sel_0 +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.SEL0 +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.SEL1.txt b/ProDOS.FX/ProDOS.S.SEL1.txt new file mode 100644 index 00000000..e2954639 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.SEL1.txt @@ -0,0 +1,404 @@ +NEW + AUTO 3,1 +* object code = sel_1 +* Bird's Better Bye at org = dispadr +*-------------------------------------- +birdbye cld + lda RROMBNK2 read ROM + stz softev + lda /dispadr set reset vector to 'dispadr' + sta softev+1 jsr setpwrc create power-up byte + lda #$A0 + jsr $C300 initialize 80 column text card + ldx #$17 + +* set up memory bitmap in global page + +L5D16 stz memmap,x P8 memory bitmap + dex + bpl L5D16 + inc memmap+$17 protect global page + lda #$CF protect zero page, stack and page 1 + sta memmap + lda #$02 + sta smparms init set mark parms pcount. + +* drive selector + + ldx numdevs get device count and + stx lstpntr store in zero page. + lda devnum get last slot/drive + bne volname + +ds2 ldx lstpntr get device list pointer. + lda devlist,x get unit number from list. + cpx #$01 make sure it's real. + bcs L5D3F if so, change list pointer. + ldx numdevs get device count. + inx +L5D3F dex decrement list pointer and restore. + stx lstpntr + +* get and store volume name + +volname sta ol_unit store unit number for online. + jsr MLI + .DA #$C5 online call + .DA ol_parms + bcs ds2 error check. + stz dlevel haven't read root directory yet. + lda pbuf+1 load description byte. + and #$0F mask for name length. + beq ds2 if 0, then try next unit. + adc #$02 add 2 to length. + tax name length in x. +vnam1 stx pbuf save the name length + lda #$2F '/' + sta pbuf+1 slash before and + sta pbuf,x after name. + stz pbuf+1,x null after complete name. + +* open and read directory + + jsr MLI + .DA #$C8 open + .DA op_parms + bcc L5D7F good open. + lda dlevel trying to open root directory ? + beq ds2 yes, just move to next volume. + jsr bell1 no, generate bell tone + jsr popdir and stay at same level. + stx pbuf + jmp keyloop +L5D7F inc dlevel + stz filecount zero file count. + lda op_refn get file reference number + sta rd_refn store in read + sta sm_refn and setmark parm lists. + lda #$2B set read parm list for + sta dhdr_len directory header length. + stz dhdr_len+1 + jsr doread read directory + bcs L5DB3 + ldx #$03 +L5D9A lda sysentry+$23,x copy directory info + sta entlen,x to zero page. + dex + bpl L5D9A + sta dhdr_len put entry length in read parm list. + lda #$01 set block file counter to 1. + sta blkfl + stz fpos_mid zero out msb's of file position + stz fpos_hi in setmark parm list. + lda filecnt any files in directory ? + ora filecnt+1 + bne L5DB5 if so, continue +L5DB3 bra L5E29 else go close directory file. +L5DB5 bit filecnt+1 check msb of file count. + bmi L5DB3 if set then done. +L5DB9 lda fpos_mid get mid byte of setmark file position. + and #$FE reset lsb + sta fpos_mid and save. + ldy blkfl block file counter + lda #$00 + cpy entblk have we read all entries in this block ? + bcc L5DCE if not, continue. + tay if so, zero y-reg and + sty blkfl reset block counter / flag + inc fpos_mid + +* set up setmark parameters for next file to be read. +* if transfer to second sector, handle it. + +L5DCC inc fpos_mid +L5DCE dey decrement file block counter + clc + bmi L5DD8 + adc entlen add entry length to acc. + bcc L5DCE determine if we flopped into 2nd half of + bcs L5DCC block, if so inc mid byte position. +L5DD8 adc #$04 add 4 and put in + sta fpos_lo low byte of setmark. + jsr MLI call mli + .DA #$CE set mark + .DA #smparms parameters address = $0060 + .HS 00 + bcs L5DB3 error + jsr doread + bcs L5DB3 error. + inc blkfl increase count of files read. + lda sysentry file type/length. + and #$F0 mask off high nibble. + beq L5DB9 deleted file, try next one. + dec filecnt decrement low file count. + bne L5DF8 + dec filecnt+1 and high if necessary. +L5DF8 ror sysentry+$1E check access bit. + bcc L5DB5 if no read, try next file. + lda sysentry+$10 get file type. + cmp #$0F directory file ? + beq L5E08 then continue. + cmp #$FF system file ? + bne L5DB5 no, read next file. +L5E08 ldx filecount get valid files read. + cpx #$80 if greater than size of filename buffer + bcs L5E29 then close directory + sta filetyps,x else store filetype in zero page + jsr namecalc and go set up storage area. + ldy #$0F +L5E15 lda sysentry,y get byte of filename + sta (fnstore),y store in directed area + dey + bpl L5E15 + iny y = 0 + and #$0F mask off low nibble (name length) + sta (fnstore),y restore in name buffer + inc filecount increment valid file counter + bne L5DB5 get next file (branch always) +L5E26 jmp ds2 error. try next unit. +L5E29 jsr MLI close directory file + .DA #$CC + .DA cl_parms + bcs L5E26 error. + jsr settxt use full screen for windows + jsr home + lda #$17 cursor at bottom of screen. + jsr TABV set vertical position. + ldy #$00 + lda #$14 horizontal position. + jsr sethorz print message. + jsr homecurs cursor to upper/left. + ldx #$00 +L5E48 lda pbuf+1,x + beq showfiles + jsr output + inx + bne L5E48 +showfiles stz valcnt + stz topname init top filename index. + lda filecount # of valid files. + beq keyloop if no files. + cmp #$15 more than what will fit on screen ? + bcc L5E61 no. + lda #$14 limit to 20 files on the screen. +L5E61 sta gp_cnt + lda #$02 set window dimensions + sta wndtop + sta wndlft + lda #$16 + sta wndwdth + sta wndbtm +L5E6F jsr nameprnt output filename to screen + inc valcnt + dec gp_cnt file counter. + bne L5E6F continue printing names. + stz valcnt + beq L5EAA if last file, it needs to be inverse. +uparrow jsr nameprnt print old name in normal. + ldx valcnt get old name number. + beq L5EAA if already at the top name + dec valcnt else fix index. + lda cv current cursor line. + cmp #$02 at top line of window ? + bne L5EAA no, move up normally. + dec topname fix offset index + lda #$16 else sroll windows down a line. + bne L5EA7 branch always. +dnarrow jsr nameprnt print old name in normal. + ldx valcnt get old name number. + inx add one. + cpx filecount + bcs L5EAA if already at last filename + stx valcnt else update index. + lda cv current cursor line. + cmp #$15 at bottom line of window ? + bne L5EAA no, move cursor normally. + inc topname update offset index + lda #$17 else scroll up a line. +L5EA7 jsr cout +L5EAA jsr setinv set inverse text mode. + jsr nameprnt output last filename. +keyloop lda kbd get keyboard input. + bpl keyloop loop until key pressed. + sta KBDSTROBE clear strobe. + jsr setnorm set normal text mode. + ldx filecount are any files displayed ? + beq L5ECB no, don't accept arrow keys or return. + cmp #$8D return ? + beq L5EF4 then run selected file. + cmp #$8A down ? + beq dnarrow move down a name. + cmp #$8B up ? + beq uparrow move up a name. +L5ECB cmp #$89 tab ? + beq L5EED new volume. + cmp #$9B esc ? + bne keyloop no, try again else pop up a directory. + +* pop a directory level + + jsr popdir + dec dlevel + bra L5EF1 +popdir ldx pbuf +L5EDD dex + lda pbuf,x + cmp #$2F slash + bne L5EDD + cpx #$01 + bne L5EEC + ldx pbuf +L5EEC rts +L5EED jmp ds2 set up new unit number. +L5EF0 inx +L5EF1 jmp vnam1 get new directory info. + +* run selected file + +L5EF4 jsr MLI set prefix + .DA #$C6 + .DA pf_parms + bcs L5EED error. + ldx valcnt get name number. + jsr namecalc set up name storage area (on return y=0) + ldx pbuf get prefix length. +L5F04 iny start at y = 1. + lda (fnstore),y get character of name. + inx + sta pbuf,x store in prefix buffer. + cpy namelen check length of name. + bcc L5F04 loop until all transferred. + stx pbuf put prefix length into buffer. + ldy valcnt get file number. + lda filetyps,y get file type. + bpl L5EF0 branch if directory. + jsr settxt reset to full window. + jsr home makes for no flash. + lda #$95 ctrl-u + jsr cout turn off 80 columns. + jsr MLI open file + .DA #$C8 + .DA op_parms + bcs L5EED if error. + lda op_refn move reference number + sta rd_refn for read. + lda #$FF read the entire file. + sta dhdr_len + sta dhdr_len+1 + jsr doread read selected file. + php save possible error. + jsr MLI close file. ignore any error from close + .DA #$CC + .DA cl_parms + plp restore status from read. + bcs L5EED if any errors. + jmp sysentry execute selected system file. + +* output messages. on entry: acc = horizontal position, +* y = index to message teminated by 0. + +sethorz sta ch +msgout lda dsp2msg,y + beq L5F57 + jsr cout + iny + bne msgout +L5F57 rts + +* name pointer calculator for name storage area + +namecalc stz fnstore+1 init high byte of 16-bit shift + txa + asl shift to high nibble + rol fnstore+1 + asl + rol fnstore+1 + asl + rol fnstore+1 + asl + rol fnstore+1 + sta fnstore low pointer + lda /iobuf + clc + adc fnstore+1 + sta fnstore+1 + ldy #$00 + lda (fnstore),y file name length + sta namelen + rts + +* output a filename line + +nameprnt lda #$02 + sta ch80col horizontal position = 2. + ldx valcnt filename number + txa + sec + sbc topname calculate line # to display name + inc + inc + jsr TABV set vertical position. + lda filetyps,x get filetype (x is unchanged by tabv). + bmi L5F99 branch if system file. + stz ch80col adjust cursor position. + lda invflg ave current inverse setting + pha + ldy #fldrmsg-dsp2msg + jsr msgout display the folder. + pla restore inverse setting. + sta invflg +L5F99 jsr outsp output a space. + jsr namecalc calc name location. +L5F9F iny y = 1 (first time). + lda (fnstore),y get name character. + jsr output put on screen. + cpy namelen end of name ? + bcc L5F9F no. +outsp lda #$A0 + bne L5FB1 branch always. +homecurs lda #$99 +output ora #$80 set high bit. +L5FB1 jmp cout output to screen. +doread jsr MLI mli read call + .DA #$CA + .DA rd_parms + rts + +* data area + +dsp2msg .AS -"RETURN: Select | TAB: Chg Vol | " + .AS -"ESC: Back" + .DA #$00 +fldrmsg .DA #$0F inverse control code + .HS 1B enable mousetext + .AS -"XY" folder characters + .HS 18 disable mousetext + .HS 0E normal control code + .HS 00 +op_parms .DA #$03 3 parms + .DA pbuf pathname + .DA op_buf file buffer +op_refn .HS 00 reference number +cl_parms .HS 01 1 parm + .HS 00 reference number. +ol_parms .HS 02 2 parms +ol_unit .HS 60 unit number, default = s6, d1 + .DA pbuf+1 data buffer +pf_parms .DA #01 one parm + .DA pbuf pathname +rd_parms .DA #04 4 parms +rd_refn .HS 01 reference number + .DA sysentry data buffer + +* these last 2 parms (4 bytes) may extend past $300 length limit since +* the request count is set prior to using the parm block and the transfer +* count isn't used at all (except by prodos) +* .HS 0000 requested length +* .HS 0000 actual length + +dhdr_len .HS 00 directory header length (actually uses 2 bytes) +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.SEL1 +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.SEL2.txt b/ProDOS.FX/ProDOS.S.SEL2.txt new file mode 100644 index 00000000..f0ee5778 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.SEL2.txt @@ -0,0 +1,440 @@ +NEW + AUTO 3,1 +* object code = sel_2 +* +* Alternate program selector segment for P8 when used in conjunction with +* gs/os. This code is used in place of the standard P8 interactive program +* selector when P8 is started up by GQuit. It is called when passing control +* from one application to another and the new application is 8-bit. This +* code first loads the specified P8 application at $2000 in bank 0 of memory. +* It then checks the message center for a possible name of a file. this file +* is passed on to the 8-bit application. This segment then passes control to +* the freshly loaded app. This code does NOT start with a CLD instruction +* (as other replacement quit code is supposed to do) because GQuit checks +* this to see if this version of quit code is available. + +GQdisp lda RRAMWRAMBNK1 read/write LC bank 1 + clc + xce 16 bit native mode. + jmp P8QUIT go to GQuit. + .HS 0000000000 offset to paragraph boundary. + .AS "GQ" id bytes so GQuit can identify this + +* load application +* +* Entry is in 16-bit native mode. Exit is in emulation mode. +* +* On entry and exit: +* Data bank register is set to $00. +* Direct register is set to $0000. +* Stack pointer is set to $01FB. +* +* Inputs: acc = value of E1_OS_Switch (0 or 1, 1 = yes to switch) +* +* This code is moved to $00/1010 and executed there. + +* first, copy the prefix passed from gs/os to our own volume name buffer +* so in case of an error setting the P8 prefix, it can be displayed in the +* error message. + + >SHORTM 8 bit accumulator + + pha save the switch status. + ldx ##inbuf point to passed prefix. + jsr copyvol copy the name into the buffer. + pla retrieve the switch status + +* go into emulation mode to load and run Prodos 8 application + + sec + xce 8 bit emulation mode + ora #$00 switching from P16 to P8 ? + beq L602D no. + +* switching from P16 to P8 so pass prefix 0 from P16 to the P8 prefix. the +* prefix is passed at $00/0200 by GQuit. + +L6020 jsr MLI set prefix + .DA #$C6 + .DA pfxparms + bcc L602D if prefix ok. + jsr gqerror error handler. + bra L6020 try again + +* load application at $2000 + +L602D xce native mode (carry clear) + >LONGX 16 bit regs, 8 bit acc. + lda pbuf+1 is the application name + cmp #$2F a complete pathname ? + bne L603D no, use prefix as volume name + ldx ##pbuf else use the application name. + jsr copyvol copy the volume name to buffer. +L603D sec back to emulation mode. + xce +L603F jsr MLI open the application file + .DA #$C8 + .DA opnparms + bcc L604C if open ok. + jsr gqerror handle error. + bra L603F try again. +L604C lda oprefnum copy ref number to parameter lists + sta eofrefn + sta rdrefnum + sta closeref + +* do a geteof call for how many bytes to read + +L6058 jsr MLI get eof + .DA #$D1 + .DA eofparms + bcc L6065 eof ok. + jsr gqerror handle error. + bra L6058 try again. + +* store the size of the file in the read parameter list + +L6065 lda eofval + sta rdcount + lda eofval+1 + sta rdcount+1 +L6071 jsr MLI read + .DA #$CA + .DA readparm + bcc L607E read ok + jsr gqerror + bra L6071 +L607E jsr MLI close + .DA #$CC + .DA closeprm + bcc L608B close ok + jsr gqerror + bra L607E +L608B jsr dolaunch check for possible 2nd pathname. + bne L6099 if none then run program + jsr ckfordrv else make sure the file is online. + bcc L6099 if so then run the program. + lda #$45 volume not found error. + bra L60AB +L6099 lda RROMBNK2 enable ROM + jmp sysentry execute the system application + +gqerror clc + xce 16 bit native mode + >LONGMX + jsr mountvol mount volume. + bcs L60AB if error. + sec back to emulation mode. + xce + rts + +* generate a fatal error while running under Prodos 8. +* on input, acc = error code. this routine does not return. + +L60AB clc native mode + xce + >LONGMX + and ##$00FF mask off high byte of error code. + pha put on stack for IntMath tool call. + pea $0000 errval>>16 + pea errval push address of string buffer. + pea $0004 make string 4 digits long. + >IIGS Int2Hex convert value to hex string. + pha make space for return value. + pea $0000 quitstr1>>16 + pea quitstr1 push first error message address + pea $0000 quitstr2>>16 + pea quitstr2 push second error message address + pea $0000 button1>>16 + pea button1 push first button text address + pea $0000 quitbtn2>>16 + pea quitbtn2 push 2nd button text address (null) + >IIGS TLTextMountVolume make the dialog box + pla retrieve button press (not used) + sec emulation mode + xce + jsr MLI quit back to GQuit + .DA #$65 + .DA quitparms + +* p8 mount volume +* +* on entry: volbuf = name of volume to mount. +* on exit: carry clear if mount volume displayed and 'return' was pressed. +* carry set if no window displayed or if had window and 'esc' pressed. + +mountvol ldy ##$0000 volbuf>>16 + ldx ##volbuf set up pointer to volume name. + +* if error is 'volume not found' or 'no disk in drive' then display the +* Mount Volume window, otherwise return with carry set. + + and ##$00FF mask just in case. + cmp ##$0045 volume not found ? + beq L6101 yes + cmp ##$002F no disk in drive ? + beq L6101 yes + sec indicate error not handled. + rts return with error code still in acc. + +L6101 pha save error code in case esc pressed. + phy pointer to volume name. + phx + tsc + phd save D reg. + tcd point D reg at stack. + lda [$01] get length byte and leading separator. + dec don't count leading separator. + xba then swap the bytes so the volume name + sta [$01] doesn't cpntain the separator. + pha room for result. + pea $0000 mountmsg>>16 + pea mountmsg + phy hi word of pointer to volume name. + inx skip separator. + phx lo word of pointer to volume name. + pea $0000 button1>>16 + pea button1 'Return' + pea $0000 button2>>16 + pea button2 'Escape' + >IIGS TLTextMountVolume + lda [$01] restore first 2 bytes of vilume name + xba back to their original positions + inc and values. + sta [$01] + pla which button: 1=Return 2=Escape. + pld restore D reg. + plx pull volume name pointer off stack + plx + cmp ##$0001 which button was pressed ? + bne L613C if Escape pressed. + clc indicate Return was pressed. + pla pull original error code off stack. + rts return with carry clear. +L613C sec indicate Escape was pressed. + pla restore error code. + rts return with carry set. + +* copy the volume name from the given pathname to the volume name buffer. +* +* inputs: x = length byte of complete pathname containing volume name. +* output: volume name is stored in volbuf. + +copyvol lda >1,x get the first slash + sta volbuf+1 + ldy ##$0002 initialize the length count. + +L6148 lda >2,x now copy the volume name up to + cmp #$2F the separating slash. + beq L6156 + sta volbuf,y + inx + iny + bra L6148 +L6156 dey fix character count. + tya length. + sta volbuf store the resultant string length. + rts + +* translate a filename message from the message center to the currently +* launching P8 application if it can accept a second filename. If found, +* copy the filename into the application's filename buffer. +* on exit, the z-flag is set if a filename was correctly passed to the +* application elst the z-flag is clear if it couldn't be done. + +dolaunch lda sysentry does the app start with a jump ? + cmp #$4C + bne L616F no, doesn't follow the convention. + lda #$EE check for the signature bytes. + cmp sysentry+3 + bne L616F 1st one doesn't match, skip it. + cmp sysentry+4 + beq L6170 both match, go get a filename message. +L616F rts just return to launch the app. + +L6170 lda #$FF put flag conditioning value on + pha the stack (assume error). + clc native 16-bit mode. + xce + >LONGMX + pha make room on stack for user id. + >IIGS MMStartUp start up the memory manager. + pla get the user id and + pha leave it on the stack. + pha + pha make room on stack for new handle. + pea $0000 + pea $000A get a 10 byte block of memory. + pha put user id on stack. + pea $0000 totally unrestricted block. + pha LocationPtr (not used) + pha + >IIGS NewHandle go get the block of memory. + pla get the handle from the stack. + plx + bcs L620A branch if error, no memory available. + phx leave the handle on the stack. + pha + pea $0002 'get' a message. + pea $0001 get a type 1 (filename) message. + phx put the message handle on the stack + pha (still in acc and x regs) + >IIGS MessageCenter + bcs L6203 branch if no message. + pha leave 4 bytes free on stack + pha (will be used as a direct page pointer) + tsc get the stack pointer. + phd save current direct register. + inc point to new direct page space. + tcd make a new direct page. + lda [$04] de-reference the handle. + sta $00 + ldy ##$0002 + lda [$04],y + sta $02 + ldy ##$0006 get the message command. + lda [$00],y + bne bad_msg if print, then skip it. + lda $00 adjust pointer to filename string. + clc + adc ##$0008 + sta $00 + bcc L61D1 + inc $02 +L61D1 lda [$00] get the length of the string. + and ##$00FF mask off high (leaving just the length) + >SHORTM 8 bit accumulator + cmp sysentry+5 check against length of app buffer. + beq L61DF if equal then continue with move. + bcs bad_msg if too long then bad message. +L61DF tay string length. +L61E0 lda [$00],y get a character. + sta sysentry+6,y store it in the app's filename buffer + sta inbuf,y and in prefix buffer. + dey + bpl L61E0 + lda #$00 change flag conditioning value on stack + sta $0D,s to indicate a filename is passed. +bad_msg + >LONGM 16-bit acc. + pld restore direct register. + pla fix stack because handle and userid + pla still on stack. + pea $0003 now delete the message (done with it). + pea $0001 message type 1. + pha garbage handle (not used). + pha + >IIGS MessageCenter go delete the message. +L6203 >IIGS DisposeHandle throw away message (handle is on stack) +L620A >IIGS MMShutDown shutdown the memory manager (userid is + sec on stack). + xce back to emulation mode. + + pla condition z-flag with value on stack. + bne L6231 then done. + ldx inbuf get length of pathname. + lda #$2F look for slash. +L621B cmp inbuf,x + beq L6225 when found, set prefix. + dex + bne L621B + bra L6231 if no slash, just skip it. +L6225 dex don't include trailing slash. + stx inbuf set new length. + jsr MLI set the P8 prefix. + .DA #$C6 + .DA pfxparms + lda #$00 set z-flag +L6231 rts and go launch the app. + +* check for disk volume +* +* on exit: +* carry clear = disk was found +* carry set = disk not found + +ckfordrv clc native mode + xce + >LONGX 16-bit regs, 8-bit acc. + ldx ##sysentry+6 point to pathname buffer. + jsr copyvol copy volume name to pathname buffer. +.1 sec emulation mode. + xce + jsr MLI get info on the volume. + .DA #$C4 + .DA gfiparms + bcc .2 branch if volume found, + clc (native mode) + xce + >LONGMX + jsr mountvol else ask user to mount the volume. + bcc .1 if pressed, then try again. + sec emulation mode. + xce + sec disk not found. +.2 rts + +* Prodos 8 parameter lists + +pfxparms .DA #01 one parm. + .DA inbuf address of prefix. +opnparms .DA #3 3 parms. + .DA pbuf pathname + .DA op_buf i/o buffer +oprefnum .HS 00 reference # +eofparms .DA #02 2 parms +eofrefn .HS 00 reference # +eofval .HS 000000 3 byte eof value +readparm .DA #04 4 parms +rdrefnum .HS 00 reference # + .DA sysentry read into $2000 (bank 0). +rdcount .HS 0000 # of bytes to read. + .HS 0000 transfer count +closeprm .DA #1 1 parm +closeref .HS 00 reference # +quitparms .DA #04 4 parms. + .HS 00 quit back to launcher (GQuit) + .HS 0000 + .HS 00 + .HS 0000 +gfiparms .DA #$0A 10 parms + .DA volbuf volume buffer + .DA #0 access + .DA #0 file type + .DA 0 aux type + .DA #0 storage type + .DA 0 blocks used + .DA 0 modification date + .DA 0 modification time + .DA 0 creation date + .DA 0 creation time + +* messages for P8 fatal error. maximum length of message is 35 characters. +* the error code will be displayed immediately after the final character. + +quitstr1 .DA #$1B + .AS "Can't run next application." +quitstr2 .DA #$14 + .AS "ProDOS Error = $" +errval .AS " " +quitbtn2 .HS 00 + +* messages for P8 mount volume. maximum length of message is 35 characters. +* the button labels must not be more than 16 characters. + +mountmsg .DA #$17 + .AS "Please insert the disk:" +button1 .DA #$0D + .AS "Accept: " + .DA #$1B mousetext on + .DA #$0F inverse on + .DA #$4D mousetext return + .DA #$0E normal on + .DA #$18 mousetext off +button2 .DA #$0B + .AS "Cancel: Esc" +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.SEL2 +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.TCLK.txt b/ProDOS.FX/ProDOS.S.TCLK.txt new file mode 100644 index 00000000..653eb518 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.TCLK.txt @@ -0,0 +1,104 @@ +NEW + AUTO 3,1 +* object code = tclock_0 +* Thunderclock driver +* hard coded for slot 1 + +* $2F00-2F7C moved to $D742 + +TCLK.START ldx TCLK.Cx2+2 clock slot = $C1. + + lda clkmode,x save current mode + pha + lda #$A3 send numeric mode byte to Thunderclock + +TCLK.Cx1 jsr wttcp + +TCLK.Cx2 jsr rdtcp read month, day of week, day of month + clc and time into input buffer. + ldx #$04 index for 5 values. + ldy #$0C read minutes 1st, month last. +.1 lda inbuf,y convert values to binary. + and #$07 no value > 5 decimal. + sta pcl 'tens' place value + asl multiply by 10 + asl + adc pcl + asl + adc inbuf+1,y add to ascii 'ones' place + sec and subtract out the ascii + sbc #$B0 + sta pcl,x save converted value. + dey index to next lowest value + dey + dey + dex are there more values? + bpl .1 if yes. + tay contains month + lsr + ror + ror + ror high bit of month held in carry + ora A1L + sta p8date save low value of date. + php save high bit of month. + and #$1F isolate day. + adc tdays-1,y (y = month) + bcc .2 branch if not Sept 13 thru 30th + adc #$03 adj for mod 7 when day > 256 +.2 sec +.3 sbc #$07 + bcs .3 loop until < 0. + adc #$07 make it in the range of 0-6. + sbc pch the delta provides years offset. + bcs .4 branch if positive + adc #$07 else make it positive again. +.4 tay + lda yradj,y look up year + plp and combine it with hi bit of month + rol + sta p8date+1 P8 date + lda A1L+1 hour + sta p8time+1 P8 time + lda A2L minute + sta p8time + pla restore previous mode. + ldx TCLK.Cx2+2 clock slot = $C1 + sta clkmode,x +TCLK.CEND rts + +* this table contains entries for the cumulative # of days in a year, +* one entry for each month. the values are modulo 256. + +tdays .DA #$00 January + .DA #$1F February + .DA #$3B March + .DA #$5A April + .DA #$78 May + .DA #$97 June + .DA #$B5 July + .DA #$D3 August + .DA #$F2 September + .DA #$14 October (MOD 256) + .DA #$33 November + .DA #$51 December + +* the following table is used to look up the current year, based on +* the current month, day and day of week. The 1st entry corresponds +* to the year in which January 1st falls on a Monday. The 2nd entry +* is the year which January 1st is Sunday, and so on backwards thru +* the days of the week. + +yradj .DA #$07 Monday + .DA #$0C Sunday + .DA #$0B Saturday + .DA #$0A Friday + .DA #$09 Thursday + .DA #$08 Wednesday + .DA #$08 Tuesday +TCLK.END .HS 000000 pad +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.TCLK +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.XDOS.A.txt b/ProDOS.FX/ProDOS.S.XDOS.A.txt new file mode 100644 index 00000000..c9912076 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.XDOS.A.txt @@ -0,0 +1,670 @@ +NEW + AUTO 3,1 +*-------------------------------------- +XDOS.MLI cld no decimal. + pla get processor status + sta spare1 save it temporarily + sty mliy save x and y + stx mlix + pla find out the address of the caller + sta A3L + clc preserve the address of the call spec. + adc #$04 + sta mliretn last MLI call return address + pla + sta A3L+1 + adc #$00 + sta mliretn+1 + lda spare1 + pha pull processor status + plp to re-enable interrupts. + + cld still no decimal + stz p8error clear any previous errors. + ldy #$01 find out if command is valid. + lda (A3L),y get command # + lsr and hash it to a range of 0-$1F + lsr + lsr + lsr + clc + adc (A3L),y + and #$1F + tax + lda (A3L),y check result to see if valid command # + cmp scnums,x + bne scnerr + + iny index to call spec parm list. + lda (A3L),y make A3L point to parameter count byte + pha in parameter block. + iny + lda (A3L),y + sta A3L+1 + pla + sta A3L +* ldy #$00 + lda pcntbl,x make sure parameter list has the correct # of parameters. + beq goclock clock has 0 parameters. + + cmp (A3L) ,y + bne scperr error if wrong count. + + lda scnums,x get call # again + cmp #MLIQUIT is it quit? + beq special if so, then call quit dispatcher + + asl carry set if bfm or dev mgr + bpl godevmgr + bcs gobfmgr + + lsr shift back down for interrupt manager + and #$03 valid calls are 0 and 1 + jsr XDOS.intmgr + bra exitmli +special jmp jspare P8 system death vector + +goclock jsr clockv go read clock. + bra exitmli no errors possible + +godevmgr lsr shift back down for device manager. + adc #$01 valid commands are 1 and 2. + sta A4L save command #. + jsr XDOS.devmgr execute read or write request. + bra exitmli + +gobfmgr lsr shift back down for block file manager. + and #$1F valid commands are 0-$13 + tax + jsr XDOS.bfmgr + +exitmli stz bubit clear backup bit + ldy p8error P8 error code + cpy #$01 if > 0 then set carry + tya and set z flag. + php disable interrupts until exit complete. + sei + lsr mliact indicate MLI done. + plx save status register until return. + lda mliretn+1 place last MLI call return address + pha on stack. return is done via 'rti' + lda mliretn so the status register is restored + pha at the same time, so + phx place status back on stack + tya return error, if any. + ldx mlix MLI X register savearea + ldy mliy MLI Y register savearea + pha + lda bnkbyt1 restore language card status + jmp HBFA0 and return. + +nodevice lda #MLI.E.NODEV no device connected. + .HS 2C BIT ABS +scnerr lda #MLI.E.BADCALL + .HS 2C BIT ABS +scperr lda #MLI.E.BADCNT + jsr GP.P8errv + bra exitmli +*-------------------------------------- +* ProDOS Device Manager +*-------------------------------------- +XDOS.devmgr php do not allow interrupts. + sei the call spec for devices must + + ldy #$05 +.1 lda (A3L),y be passed to drivers in page zero: + sta A4L,y + dey + bne .1 + + ldx buf+1 buffer page + stx usrbuf+1 to user buffer + inx + inx + lda buf is buffer page aligned (nn00) ? + beq .2 branch if it is + inx else account for 3-page straddle + +.2 jsr vldbuf1 make sure user buffer is not + bcs dvmgrerr conflicting with protected ram. + jsr dmgr call internal entry for device dispatch + bcs dvmgrerr branch if error + plp + clc no error + rts + +dvmgrerr plp restore interrupt status +gosyserr jsr GP.P8errv +*-------------------------------------- +dmgr lda unitnum get device # and + and #$F0 strip misc lower nibble + sta unitnum then save it. + lsr use as index to device table + lsr + lsr + tax +gocmd jmp (drivertbl1,x) goto driver (or error if no driver) +*-------------------------------------- +* ProDOS interrupt manager +*-------------------------------------- +XDOS.intmgr sta A4L interrupt command + lsr allocate interrupt or deallocate? + bcs dealcint branch if deallocate. + + ldx #$03 test for a free interrupt space in tbl. + +.1 lda inttbl-2,x test high address for 0. + bne .2 branch if spot occupied. + + ldy #$03 get address of routine. + lda (A3L),y must not be zero page. + beq badint error if it is. + sta inttbl-2,x save high address + dey + lda (A3L),y + sta inttbl-3,x and low address. + txa return interrupt # in range 1-4 + lsr + dey + sta (A3L),y pass back to user. + clc no errors. + rts + +.2 inx + inx next lower priority spot + cpx #$0B are all 4 already allocated? + bne .1 branch if not. + + lda #MLI.E.IRQFULL interrupt table full + .HS 2C BIT ABS +badint lda #MLI.E.INVPARAM invalid parameter. + jsr GP.P8errv + +dealcint ldy #$01 zero out interrupt vector + lda (A3L),y but make sure it is a valid #. + beq badint error if < 1 + + cmp #$05 or > 4 + bcs badint + + asl + tax + lda #$00 now clear it + sta inttbl-2,x + sta inttbl-1,x + clc + rts +*-------------------------------------- +irqrecev lda accsav get acc from where old ROM put it. + sta p8areg + stx p8xreg entry point on ram card interrupt + sty p8yreg + tsx + stx p8sreg + lda irqflag irq flag = 0 if old roms + bne .1 and 1 if new roms. + + pla restore return address and p-reg. + sta p8preg + pla + sta intadr interrupt return address + pla + sta intadr+1 +.1 txs + lda mslot set up to re-enable $Cn00 rom + sta irqdev+2 + + ldx #$FA save 6 bytes of page 0 + +.2 lda $00,x + sta svzerop-$FA,x + inx + bne .2 + +* poll interrupt routines for a claimer + + ldx #0 +.3 stx irqXindex + + lda inttbl+1,x test for a valid routine. + beq .4 branch if no routine. + + jsr gointX execute + + bcc irqdone + +.4 ldx irqXindex + inx + inx + cpx #10 + bne .3 + + inc irqcount allow 255 unclaimed interrupts + bne irqdone before system death. + + lda #$01 bad irq so + jsr sysdeath kill the system. + +irqdone ldx #$FA + +H31AE lda svzerop-$FA,x restore the zero page + sta $00,x + inx + bne H31AE + + lda irqflag check for old roms. + bne H31DD branch if new roms. + + ldy p8yreg restore registers. + ldx p8xreg + lda CLRC8ROM re-enable i/o card. +irqdev lda $C100 Cn is self modifying. + lda irqdev+2 restore device id. + sta mslot slot being accessed. + +H31DD jmp GP.IrqExit do necessary bank switches and return. + +irqflag .HS 00 0 = old roms. 1 = new roms. +irqcount .HS 00 # of unclaimed interrupts. +irqXindex .HS 00 +svzerop .HS 000000000000 + +gointX jmp (inttbl,x) interrupt routine x + +XDOS.syserr sta p8error P8 error code + plx + plx pop 1 level of return + sec + rts + +sysdeath1 tax death error code. + sta CLR80DISP disable 80 col hardware. + lda SETTEXT switch in text. + lda cortflag is this a Cortland? + beq H321A if not, don't use super hires switch. + stz newvideo force off super hires. +H321A lda CLRPAGE2 switch in text page 1. + ldy #$13 + +H321F lda #$20 inverse space border + sta vline11+10,y + sta vline13+10,y + lda deathmsg,y + sta vline12+10,y 'RESTART SYSTEM-$0x' + dey + bpl H321F + + txa x = death error code + and #$0F convert to ascii + ora #$B0 + cmp #$BA + bcc H323B branch if not > 9. + adc #$06 inc to alpha a-f +H323B sta vline12+28 death error code 1 to F + bra * end of xdos mli +*-------------------------------------- +* ProDOS Block File Manager +*-------------------------------------- +XDOS.bfmgr lda disptch,x translate into command address. + asl bit 7 indicates pathname to process + sta cmdtemp + and #$3F bit 6 is refnum, 5 is time to process + tax + lda cmdtable,x move address to indirect jump + sta H3274+1 + lda cmdtable+1,x high byte + sta H3274+2 + lda #$20 init backup bit flag + sta bkbitflg to say 'file modified' + bcc nopath + + jsr setpath process pathname before calling command + bcs errorsys branch if bad name. + +nopath asl cmdtemp test for refnum processing + bcc nopreref + + jsr findfcb set pointers to fcb and vcb of file + bcs errorsys + +nopreref asl cmdtemp check for necessity of time stamp + bcc H3274 + + jsr clockv date/time +H3274 jsr $FFFF SELF MODIFIED : execute command + bcc goodop + +errorsys jsr GP.P8errv +goodop rts + +setpath ldy #$01 index to pathname pointer + lda (A3L),y low pointer address + sta zpt + iny + lda (A3L),y hi pointer address + sta zpt+1 + +* entry used by rename for 2nd pathname. + +synpath ldx #$00 x = index to pathbuf + ldy #$00 y = index to input pathname. + stx prfxflg assume prefix is in use. + stx pathbuf mark pathbuf = nothing processed. + lda (zpt),y validate pathname length > 0 and < 65 + beq errsyn + cmp #$41 + bcs errsyn + sta pathcnt this is used to compare for + inc pathcnt end of pathname processing. + iny now check for full pathname... + lda (zpt),y (full name if starts with '/') + ora #$80 + cmp #$AF + bne H32AD branch if prefix appended. + sta prfxflg set prefix flag = prefix not used. + iny index to 1st character of pathname. +H32AD lda #$FF set current position of pathbuf + sta pathbuf,x to indicate end of pathname. + sta namcnt $FF = no chars processed in local name. + stx namptr pointer to local name length byte. +H32B8 cpy pathcnt done with pathname processing? + bcs endpath + lda (zpt),y get character + and #$7F + inx prepare for next char + iny + cmp #$2F is it delimiter '/' ? + beq endname yes + cmp #$61 lowercase? + bcc H32CD no + and #$5F shift to uppercase +H32CD sta pathbuf,x store char + inc namcnt is it the 1st char of a local name? + bne H32DA no + inc namcnt increment to 1 + bne H32E6 1st char must be alpha (always taken) +H32DA cmp #$2E is it '.' ? + beq H32B8 ok, then do next char + cmp #$30 at least a '0' ? + bcc errsyn error if not + cmp #$3A is it numeric? + bcc H32B8 yes, get next char +H32E6 cmp #$41 at least an 'a' ? + bcc errsyn error if not + cmp #$5B is it > 'z' ? + bcc H32B8 branch if valid alpha to get next char +errsyn sec bad pathname + lda #$40 + rts +endpath lda #$00 end pathname with a 0 + bit namcnt also make sure count is positive + bpl H32FD + sta namcnt + dex +H32FD inx + sta pathbuf,x + beq errsyn error if '/' only. + stx pathcnt save length of pathname + tax +endname lda namcnt validate local name < 16 + cmp #$10 + bcs errsyn + phx save pointer + ldx namptr get index to beginning of local name + sta pathbuf,x save local name's length + plx restore pointer + bne H32AD branch if more names to process + clc probably no error, but + lda prfxflg make sure all pathnames are prefixed + bne H3323 or begin with a '/'. + lda newpfxptr must be non-zero + beq errsyn +H3323 rts + +* set prefix command + +setprefx jsr setpath call is made to detect if a null path. + bcc H3333 path ok. + ldy pathbuf is it a null pathname? + bne pfxerr error if not + jsr stypfx indicate null prefix + clc no error + rts +H3333 jsr findfile go find specified prefix directory. + bcc H333C if no error. + cmp #$40 bad pathname. + bne pfxerr branch if error is not root directory. + +H333C lda d_stor make sure last local name is dir type + and #$D0 (either root or sub). + eor #$D0 directory? + bne ptyperr wrong type + ldy prfxflg new or appended prefix? + bne H334D + lda newpfxptr append new prefix to old +H334D tay + sec find new beginning of prefix + sbc pathcnt + cmp #$C0 too long? + bcc errsyn then error + + tax + jsr stapfx + lda d_dev save device # + sta p_dev + lda d_frst and address of 1st block + sta p_blok + lda d_frst+1 + sta p_blok+1 + +movprfx lda pathbuf,y + sta pathbuf,x + iny + inx + bne movprfx + clc good prefix + rts +ptyperr lda #$4B filetype error (not a directory) +pfxerr sec + rts + +* get prefix command + +getprefx clc calc how big a buffer is needed. + ldy #$01 get index to users pathname buffer + lda (A3L),y + sta usrbuf user buffer ptr + iny + lda (A3L),y + sta usrbuf+1 + stz cbytes+1 set buffer length at 64 char max + lda #$40 + sta cbytes + jsr valdbuf go validate prefix buffer address + bcs pfxerr + ldy #$00 y = indirect index to user buffer. + lda newpfxptr get address of beginning of prefix + tax + beq nulprfx if null prefix. + eor #$FF get total length of prefix + adc #$02 add 2 for leading and trailing slashes. +nulprfx sta (usrbuf),y store length in user's buffer. + beq gotprfx branch if null prefix. +sendprfx iny inc to next user buffer location. + lda pathbuf,x get next char of prefix. +sndlimit sta (usrbuf),y give char to user. + and #$F0 check for length descriptor. + bne H33B3 branch if regular character + + lda #$2F otherwise, substitute a slash. + bne sndlimit branch always + +H33B3 inx + bne sendprfx branch if more to send. + iny + lda #$2F end with '/' + sta (usrbuf),y +gotprfx clc no error + rts +findfcb ldy #$01 index to ref# + lda (A3L),y is it a valid file# ? + beq badref must not be 0. + cmp #$09 must be 1 to 8 only. + bcs badref + pha + dec + lsr + ror + ror + ror multiply by 32. + sta fcbptr used as an index to fcb + tay + pla restore ref# in acc + cmp fcbbuf,y + bne errnoref +fndfcbuf lda fcbbuf+11,y get page address of file buffer. + jsr getbufadr get file's address into bufaddrl,h + ldx bufaddrh (y=fcbptr preserved) + beq fcbdead fcb corrupted + stx datptr+1 save ptr to data area of buffer + inx + inx index block always 2 pages after data + stx zpt+1 + lda fcbbuf+1,y also set up device # + sta devnum + lda bufaddrl + sta datptr index and data buffers always on + sta zpt page boundaries. +fndfvol tax search for associated vcb + lda vcbbuf+16,x + cmp fcbbuf+1,y is this vcb the same device? + beq tstvopen if it is, make sure volume is active. +nxtfvol txa adjust index to next vcb. + clc + adc #$20 + bcc fndfvol loop until volume found. + lda #$0A open file has no volume so + jsr sysdeath kill the system. + +fcbdead lda #$0B fcb error so + jsr sysdeath kill the system. + +tstvopen lda vcbbuf,x make sure this vcb is open. + beq nxtfvol branch if it is not active. + stx vcbptr save ptr to good vcb. + clc no error + rts + +errnoref lda #$00 put a zero into this fcb to + sta fcbbuf,y show free fcb. + +badref lda #MLI.E.BADREF requested refnum is + sec illegal (out of range) + rts + +* online command + +online jsr mvdbufr figure out how big buffer has to be. + stz cbytes set this for valdbuf routine. + stz cbytes+1 + ldy #$01 + lda (A3L),y if 0 then cbytes=$100 else $010 for one + and #$F0 device. mask out unused nibble. + sta devnum last device used. + beq H343C branch if all devices. + lda #$10 cbytes = $010 + sta cbytes + bne H343F always taken +H343C inc cbytes+1 cbytes = $100 +H343F jsr valdbuf go validate buffer range against + bcs onlinerr allocated memory. + lda #$00 zero out user buffer space + ldy cbytes +H3449 dey + sta (usrbuf),y + bne H3449 + sta namptr used as pointer to user buffer. + lda devnum get device # again. + bne online1 branch if only 1 device to process. + jsr mvdevnums get list of currently recognized dev's. +H3459 phx save index to last item on list + lda loklst,x + sta devnum save desired device to look at. + jsr online1 log this volume and return it's name. + lda namptr inc pointer for next device + clc + adc #$10 + sta namptr + plx get index to device list. + dex next device. + bpl H3459 branch if there is another device. + lda #$00 no errors for multiple on-line + clc +onlinerr rts + +online1 jsr fnddvcb see if it has already been logged in. + bcs olinerr1 branch if vcb is full. + ldx #$00 read in root (volume) directory + lda #$02 + jsr rdblk read it into general purpose buffer. + ldx vcbptr index to the vcb entry. + bcc volfound branch if read was ok. + tay error value. + lda vcbbuf+17,x don't take the vcb offline if + bne rtrnerr there are active files present. + sta vcbbuf,x now take the volume offline + sta vcbbuf+16,x +rtrnerr tya error value. + bcs olinerr1 branch if unable to read. +volfound lda vcbbuf,x has it been logged in before? + beq H349E if not. + lda vcbbuf+17,x it has, are there active files? + bmi H34AA branch if volume is currently busy. +H349E jsr logvcb1 go log it in. + bcs olinerr1 branch if there is a problem. + lda #$57 anticipate a duplicate active volume + bit duplflag exits. + bmi olinerr1 branch if so. +H34AA ldx vcbptr + jsr cmpvcb does vol read compare with logged vol? + lda #$2E anticipate wrong volume mounted. + bcc H34D0 branch if ok. +olinerr1 pha save error code. + jsr svdevn report what device has problem. + pla error code. + iny tell what error was encountered. + sta (usrbuf),y + cmp #$57 duplicate volume error? + bne H34CE no. + + iny report which other device has same name + ldx vcbentry + lda vcbbuf+16,x + sta (usrbuf),y + stz duplflag clear duplicate flag. + lda #$57 duplicate volume error code. +H34CE sec flag error + rts + +H34D0 lda vcbbuf,x get volume name count + sta namcnt + ldy namptr index to user's buffer. + +H34D9 lda vcbbuf,x move name to user's buffer + sta (usrbuf),y + inx + iny + dec namcnt + bpl H34D9 + +svdevn ldy namptr index to 1st byte of this entry. + lda devnum upper nibble = device# and + ora (usrbuf),y lower nibble = name length. + sta (usrbuf),y + clc no errors + rts end of block file manager +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.XDOS.A +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.XDOS.B.txt b/ProDOS.FX/ProDOS.S.XDOS.B.txt new file mode 100644 index 00000000..d8600bea --- /dev/null +++ b/ProDOS.FX/ProDOS.S.XDOS.B.txt @@ -0,0 +1,890 @@ +NEW + AUTO 3,1 + +* create file + +create jsr lookfile check for duplicate, get free entry + bcs tstfnf error code may be 'file not found' + lda #MLI.E.DUPFILE name already exists +crerr1 sec + rts + +tstfnf cmp #MLI.E.FNOTFND 'file not found' is ok + bne crerr1 otherwise exit with error. + + ldy #$07 test for tree or directory file, + lda (A3L),y no other kinds are legal. + cmp #$04 is it seed, sapling or tree? + bcc tstdspc branch if it is + + cmp #$0D + bne ctyperr report type error if not directory. + +tstdspc lda devnum make sure destination device + jsr twrprot1 is not write protected. + bcs H351D + + lda nofree is there space in directory to + beq xtndir add this file? branch if not + jmp creat1 otherwise, go create file. + +ctyperr lda #MLI.E.UNSUPST filetype error + sec +H351D rts + +xtndir lda own_blk before extending directory, + ora own_blk+1 make sure it's a subdirectory. + bne H352A + + lda #MLI.E.DIRFULL otherwise, directory full error + sec + rts + +H352A lda bloknml preserve disk address of current (last) + pha directory link, before allocating an + lda bloknml+1 extended block. + pha + jsr alc1blk allocate a block for extending directory + plx + stx bloknml+1 restore block addr of dir info in gbuf + plx + stx bloknml + bcs H351D unable to allocate. + + sta gbuf+2 save block address in y,a to + sty gbuf+3 current directory. + jsr wrtgbuf update directory block with new link. + bcs H351D if error + + ldx #$01 + +swpbloks lda bloknml,x prepare new directory block + sta gbuf,x using current block as back link + lda gbuf+2,x + sta bloknml,x and save new block as next to be written + dex + bpl swpbloks + inx + txa x and a = 0 + +clrdir sta gbuf+2,x + sta gbuf+$100,x + inx + bne clrdir + + jsr wrtgbuf write prepared directory extension. + bcs H351D if error + + lda own_blk + ldx own_blk+1 + jsr rdblk read in parent directory block + ldx own_ent and calc entry address. + lda /gbuf + sta zpt+1 + lda #$04 +ocalc clc + dex has entry address been calulated? + beq H3584 if yes. + adc own_len next entry address + bcc ocalc + inc zpt+1 entry must be in 2nd 256 bytes of block + bcs ocalc always taken. + +H3584 sta zpt + ldy #$13 index to block count +H3588 lda (zpt),y + adc dinctbl-$13,y add 1 to block count and + sta (zpt),y + iny + tya $200 to the directory's eof. + eor #$18 done with usage/eof update? + bne H3588 branch if not. + + jsr wrtgbuf go update parent. + bcs crerr2 + + jmp create +crerr2 rts return and report errors + +creat1 ldx #$00 zero out gbuf +H35A0 stz gbuf,x + stz gbuf+$100,x and data block of file. + inx + bne H35A0 + ldy #$0B move user specified date/time +cmvtime lda (A3L),y to directory. + sta d_filid,y + txa if all 4 bytes of date/time = 0 + ora (A3L),y then use built-in date/time. + tax + dey + cpy #$07 + bne cmvtime + txa does user want default time? + bne cmvname if not. + ldx #$03 +mvdftime lda p8date,x move current default date/time + sta d_credt,x + dex + bpl mvdftime +cmvname lda (A3L),y y = index to file kind. + cmp #$04 + lda #$10 assume tree type + bcc csvfkind + lda #$D0 it's directory. +csvfkind ldx namptr index to local name of pathname. + ora pathbuf,x combine file kind with name length. + sta d_stor sos calls this 'storage type'. + and #$0F strip back to name length + tay and use as counter for move. + clc + adc namptr calc end of name + tax +crname lda pathbuf,x move local name as filename + sta d_stor,y + dex + dey + bne crname + ldy #$03 index to 'access' parameter + lda (A3L),y + sta d_attr + iny also move 'file identification' + lda (A3L),y + sta d_filid +cmvauxid iny move auxillary identification bytes + lda (A3L),y + sta d_auxid-5,y + cpy #$06 + bne cmvauxid + lda xdosver save current xdos version # + sta d_sosver + lda compat and backward compatibility # + sta d_comp + lda #$01 usage is always 1 block + sta d_usage + lda d_head place back pointer to header block + sta d_dhdr + lda d_head+1 + sta d_dhdr+1 + lda d_stor storage type. + and #$E0 is it a directory? + beq cralcblk branch if seed file. + ldx #$1E move header to data block +cmvheadr lda d_stor,x + sta gbuf+4,x + dex + bpl cmvheadr + eor #$30 + sta gbuf+4 make it a directory header mark. + ldx #$07 overwrite password area and other +cmvpass lda pass,x header info. + sta gbuf+20,x + lda xdosver,x + sta gbuf+32,x + dex + bpl cmvpass + ldx #$02 and include info about parent directory + stx d_eof+1 +cmvparnt lda d_entblk,x + sta gbuf+39,x + dex + bpl cmvparnt + lda h_entln lastly, the length of parent's + sta gbuf+42 directory entries. +cralcblk jsr alc1blk get address of file's data block + bcs crerr3 + sta d_frst + sty d_frst+1 + sta bloknml + sty bloknml+1 + jsr wrtgbuf go write data block of file + bcs crerr3 + inc h_fcnt add 1 to total # of files in this dir + bne credone + inc h_fcnt+1 +credone jsr drevise go revise directories with new file + bcs crerr3 + jmp upbmap lastly, update volume bitmap +entcalc lda /gbuf set high address of dir entry + sta zpt+1 index pointer. + lda #$04 calc address of entry based + ldx d_entnum on the entry #. +H3689 clc +H368A dex addr = gbuf + ((d_entnum-1) * h_entln) + beq H3696 branch with carry clear = no errors. + adc h_entln + bcc H368A + inc zpt+1 inc hi address. + bcs H3689 always. +H3696 sta zpt newly calculated low address. +crerr3 rts carry set if error. + +drevise lda p8date + beq drevise1 if no clock, then don't mod date/time. + ldx #$03 +modtime lda p8date,x move last modification date/time + sta d_moddt,x to entry being updated. + dex + bpl modtime +drevise1 lda d_attr mark entry as backupable + ora bkbitflg (bit 5 = backup needed) + sta d_attr + lda d_dev get device # of directory + sta devnum to be revised + lda d_entblk and address of direcotry block. + ldx d_entblk+1 + jsr rdblk read block into general purpose buffer + bcs crerr3 + jsr entcalc fix up ptr to entry location within gbuf. + ldy h_entln now move 'd.' info to directory. + dey +H36CA lda d_stor,y + sta (zpt),y + dey + bpl H36CA + lda d_head is the entry block same as + cmp bloknml the entry's header block? + bne H36E0 if no, go save entry block + lda d_head+1 then maybe, so test high addresses. + cmp bloknml+1 + beq uphead branch if they are the same block. +H36E0 jsr wrtgbuf go write updated directory block. + bcs crerr3 + lda d_head get address of header block and + ldx d_head+1 + jsr rdblk go read in header block to modify. + bcs crerr3 +uphead ldy #$01 update current # of files in this dir. +H36F2 lda h_fcnt,y + sta gbuf+37,y (current entry count) + dey + bpl H36F2 + lda h_attr also update header's attributes. + sta gbuf+34 + jsr wrtgbuf go write updated header + bcs H375A +ripple lda gbuf+4 test for 'root' directory because + and #$F0 if it is, then directory revision + eor #$F0 is complete (leaves carry clear). + beq H3770 branch if done. + lda gbuf+41 get entry # + sta d_entnum + lda gbuf+42 and the length of ertries in that dir + sta h_entln + lda gbuf+39 get addr of parent entry's dir block + ldx gbuf+40 + jsr rdblk read it + bcs H375A + jsr entcalc get indirect ptr to parent entry in gbuf + lda p8date don't touch mod + beq H373B if no clock... + ldx #$03 update the modification date & time + ldy #$24 for this entry too +H3732 lda p8date,x + sta (zpt),y + dey + dex + bpl H3732 +H373B jsr wrtgbuf write updated entry back to disk. + bcs H375A if error. + ldy #$25 compare current block # to this + lda (zpt),y entry's header block. + iny + cmp bloknml are low addresses the same? + sta bloknml + bne H3751 branch if entry doesn't reside in same + lda (zpt),y block as header. + cmp bloknml+1 are high address the same? + beq ripple they are the same, continue to root dir. +H3751 lda (zpt),y not same so read in this dir's header. + sta bloknml+1 + jsr rdgbuf + bcc ripple continue if read was good +H375A rts +tsterr lda #$52 not tree or dir, unrecognized type + sec + rts +tstsos lda gbuf pointer to previous dir block + ora gbuf+1 must be null + bne tsterr + lda gbuf+4 test for header + and #$E0 + cmp #$E0 + bne tsterr +H3770 clc no error + rts +findfile jsr lookfile see if file exists + bcs nofind +moventry ldy h_entln +H377A lda (zpt),y move entry into storage + sta d_stor,y + dey + bpl H377A + lda #$00 no errors +nofind rts + +lookfile jsr preproot go find volume + bcs fnderr + + bne lookfil0 branch if more than root + lda /gbuf otherwise, report a bad path error + sta zpt+1 (but 1st create a phantom entry + lda #$04 for open) + sta zpt + + ldy #$1F move in id and date info + +phantm1 lda (zpt),y + sta d_stor,y + dey + cpy #$17 + bne phantm1 + +phantm2 lda rootstuf-$10,y + sta d_stor,y + dey + cpy #$0F + bne phantm2 + lda #$D0 fake directory file + sta d_stor + lda gbuf+2 check forward link. + ora gbuf+3 if non-zero, assume full sized directory + bne H37C2 else assume it's the slot 3 /RAM volume + lda #$02 so reset eof and blocks_used fields + sta d_eof+1 + lda #$01 + sta d_usage +H37C2 lda #MLI.E.INVPATH bad path (carry set) + rts +lookfil0 stz nofree reset free entry indicator. + sec dir to be searched has header in this block. +L37C9 stz totent reset entry counter. + jsr looknam look for name pointed to by pnptr. + bcc namfound if name was found. + lda entcntl have we looked at all of the + sbc totent entries in this directory? + bcc L37E2 maybe, check hi count. + bne L37EB no, read next directory block. + cmp entcnth has the last entry been looked at? + beq errfnf yes, give 'file not found' error + bne L37EB or branch always. +L37E2 dec entcnth should be at least one + bpl L37EB so this should be branch always... + +errdir lda #MLI.E.BADDIR directory error +fnderr sec + rts + +L37EB sta entcntl keep a running count. + lda /gbuf reset indirect pointer + sta zpt+1 + lda gbuf+2 get link to next dir block + bne L37FC (if there is one). + cmp gbuf+3 are both zero, i.e. no link? if so, + beq errdir then not all entries were acct'd for. +L37FC ldx gbuf+3 acc has value for block# (low). + jsr rdblk go read the next linked directory. + bcc L37C9 if no error. + rts return error in acc. +errfnf lda nofree was any free entry found? + bne fnf0 + lda gbuf+2 test link + bne L3814 + cmp gbuf+3 if both are 0 then give up. + beq fnf0 report 'not found'. +L3814 sta d_entblk + lda gbuf+3 + sta d_entblk+1 assume 1st entry of next block + lda #$01 is free for use. + sta d_entnum mark as valid (for create) + sta nofree +fnf0 jsr nxtpnam1 'file not found' or 'path not found'? +errpath1 sec if non-zero then 'path not found' + beq fnf1 + + lda #MLI.E.PNOTFND path not found + rts + +fnf1 lda #MLI.E.FNOTFND file not found + rts + +namfound jsr nxtpname adj index to next name in path. + beq filfound branch if that was the last name. + ldy #$00 be sure this is a directory entry. + lda (zpt),y high nibble will tell. + and #$F0 + cmp #$D0 is it a subdirectory? + bne errpath1 error if not. + ldy #$11 get address of 1st subdirectory block + lda (zpt),y + sta bloknml (no checking done for a valid block#) + iny + sta d_head save as file's header block too + lda (zpt),y + sta bloknml+1 + sta d_head+1 + jsr rdgbuf read subdirectory into gbuf. + bcs fnderr1 if error. + lda gbuf+37 get the # of files contained in this + sta entcntl directory. + lda gbuf+38 + sta entcnth + lda gbuf+20 make sure password is disabled + ldx #$00 + sec + rol +L3869 bcc L386C + inx +L386C asl + bne L3869 + cpx #$05 is password disabled? + beq movhead + + lda #MLI.E.INCFF directory is not compatible +fnderr1 sec + rts +movhead jsr movhed0 move directory info. + jmp lookfil0 do next local pathname. + +movhed0 ldx #$0A move this directory info +L387F lda gbuf+28,x + sta h_credt,x + dex + bpl L387F + lda gbuf+4 if this is root, then nothing to do + and #$F0 + eor #$F0 test header type. + beq L389C branch if root + ldx #$03 otherwise, save owner info about +L3893 lda gbuf+39,x this header. + sta own_blk,x + dex + bpl L3893 +L389C rts + +filfound lda h_maxent figure out which entry # this is + sec + sbc cntent max entries - count entries + 1 + adc #$00 = entry # (carry was set) + sta d_entnum + lda bloknml and indicate block # of this directory + sta d_entblk + lda bloknml+1 + sta d_entblk+1 + clc + rts +looknam lda h_maxent reset count of files per block + sta cntent + lda /gbuf + sta zpt+1 + lda #$04 +L38C1 sta zpt reset indirect pointer to gbuf + bcs L38F8 branch if this block contains a header + ldy #$00 + lda (zpt),y get length of name in directory. + bne isname branch if there is a name. + lda nofree test if a free entry has been declared. + bne L38F8 yes, inc to next entry. + jsr filfound set address for current entry. + + inc nofree indicate a free spot has been found. + bne L38F8 always. +isname and #$0F strip byte (is checked by 'filfound') + inc totent inc count of valid files found. + sta namcnt save name length as counter. + ldx namptr get index to current path. + cmp pathbuf,x are both names the same length? + bne L38F8 no, inc to next entry. +cmpname inx (first) next letter index + iny + lda (zpt),y compare names letter by letter + cmp pathbuf,x + bne L38F8 + dec namcnt all letters compared? + bne cmpname no, continue. + clc a match is found. +noname rts +L38F8 dec cntent checked all entries in this block? + sec + beq noname yes, no name match. + lda h_entln add entry length to current pointer + clc + adc zpt + bcc L38C1 branch if still in 1st page. + inc zpt+1 look on 2nd page. + clc carry should always be clear before + bcc L38C1 looking at next. + +preproot jsr findvol search vcb's and dev's for spec'd volume + bcs novolume + lda #$00 zero out directory temps + ldy #$42 +L3914 sta own_blk,y and owner info + dey + bpl L3914 + lda devnum setup device # for this directory + sta d_dev + jsr movhed0 setup other header info from directory + ldy #$01 in gbuf and clean up misc info. + ldx vcbptr + inx +L3929 lda vcbbuf+18,x misc info includes + sta h_tblk,y total # of blocks, + lda vcbbuf+26,x the address of the 1st bitmap, + sta h_bmap,y + lda bloknml,y directory's disk address, + sta d_head,y + lda h_fcnt,y and setting up a counter for the # of + sta entcntl,y files in this directory. + dex + dey + bpl L3929 +nxtpname jsr nxtpnam1 get new namptr in y and namlen in acc. + sty namptr save new pathname pointer. + rts (status reg according to accumulator) +nxtpnam1 ldy namptr inc pathname pointer to next name + lda pathbuf,y in the path. + sec + adc namptr if this addition results in zero, + tay then prefixed directory has been moved + bne L395F to another device. branch if not. + lda devnum revise devnum for prefixed directory + sta p_dev +L395F lda pathbuf,y test for end of name. + clc no errors +novolume rts + +findvol lda #$00 + ldy preflag use prefix volume name to look up vcb. + bit prfxflg is this a prefixed path? + bpl L396F branch if it is + tay set ptr to volume name +L396F sty vnptr and save. + sta devnum zero out dev# until vcb located. +L3975 pha acc now used as vcb lookup index. + tax index pointer to x. + lda vcbbuf,x get vcb volume name length. + bne L3987 branch if claimed vcb to be tested. +L397C ldy vnptr restore pointer to requested vol name. + pla now adj vcb index to next vcb entry. + clc + adc #$20 + bcc L3975 branch if more vcb's to check + bcs L39D4 otherwise go look for unlogged volumes. +L3987 sta namcnt save length of vol name to be compared. +L398A cmp pathbuf,y is it the same as requested vol name? + bne L397C branch if not + inx + iny next character + lda vcbbuf,x + dec namcnt last character? + bpl L398A if not. + plx restore pointer to matching vcb. + stx vcbptr save it for future reference. + lda vcbbuf+16,x get it's device # + sta devnum and save it. + stz bloknml+1 assume prefix is not used and + lda #$02 that root directory is to be used. + sta bloknml + lda vnptr = 0 if no prefix. +L39AC tay if prefix then find ptr to prefixed + sta namptr dir name. save path ptr. + beq L39C2 branch if no prefix. + sec + adc pathbuf,y inc to next dir in prefix path. + bcc L39AC branch if another dir in prefix. + lda p_blok volume verification will occur at + sta bloknml subdirectory level. + lda p_blok+1 + sta bloknml+1 + +* verify volume name + +L39C2 jsr rdgbuf read in directory (or prefix dir) + bcs L39CC if error then look on other devices. + jsr cmppnam compare dir name with path name. + bcc L39F0 if they match, stop looking. +L39CC ldx vcbptr check if current (matched) vcb is active + lda vcbbuf+17,x i.e. does it have open files? + bmi L39ED report not found if active. +L39D4 lda vnptr make path ptr same as volume ptr + sta namptr + jsr mvdevnums copy all device #'s to be examined. + lda devnum log current device 1st before searching + bne L39F1 others. +L39E2 ldx numdevs scan look list for devices we need +L39E5 lda loklst,x to search for the requested volume. + bne L39F4 branch if we've a device to look at. + dex + bpl L39E5 look at next one. +L39ED lda #MLI.E.VNOTFND no mounted volume + sec error +L39F0 rts + +L39F1 ldx numdevs now remove the device from the list +L39F4 cmp loklst,x of prospective devices. + beq L39FE branch if match. + dex look until found. + bpl L39F4 always taken (usually) unless + bmi L39ED if dev was removed from devlst (/RAM). +L39FE sta devnum preserve device to be checked next. + stz loklst,x mark this one as tested. + jsr fnddvcb find vcb that claims this dev (if any). + bcs L3A29 branch if vcb full. + ldx vcbptr did fndvcb find it or return free vcb? + lda vcbbuf,x + beq L3A16 if free vcb. + lda vcbbuf+17,x is this volume active? + bmi L39E2 if so, no need to re-log. +L3A16 lda #$02 go read root dir into gbuf + ldx #$00 + jsr rdblk + bcs L39E2 ignore if unable to read. + jsr logvcb go log in volume name. + bcs L39E2 look at next if non-xdos disk mounted. + jsr cmppnam is this the volume ? + bcs L39E2 if not +L3A29 rts +mvdevnums ldx numdevs copy all dev #'s to be checked. +L3A2D lda devlist,x active device list. + and #$F0 strip device type info. + sta loklst,x copy them to a temp workspace + dex + bpl L3A2D + ldx numdevs + rts +fnddvcb lda #$00 look for vcb with this device# + ldy #$FF +L3A40 tax new index to next vcb + lda vcbbuf+16,x check all devnums + cmp devnum is this the vcb? + bne L3A4E if not + stx vcbptr + clc indicates found + rts +L3A4E lda vcbbuf,x is this a free vcb? + bne L3A57 if not + iny + stx vcbptr +L3A57 txa + clc inc index to next vcb + adc #$20 + bne L3A40 + tya any free vcb's available? + bpl L3A79 yes + lda #$00 look for an entry to kick out +L3A62 tax + lda vcbbuf+17,x any open files? + bpl L3A70 no, kick this one out. + txa next vcb + clc + adc #$20 (vcb entry size) + bne L3A62 + beq L3A7A all vcb entries have open files +L3A70 stx vcbptr save entry index. + stz vcbbuf,x free this entry + stz vcbbuf+16,x +L3A79 clc no error. +L3A7A lda #$55 # vcb full error + rts +cmppnam ldx #$00 index to directory name. + ldy namptr index to pathname. + lda gbuf+4 get dir name length and type. + cmp #$E0 is it a directory? + bcc L3A90 if not. + and #$0F isolate name length and + sta namcnt save as a counter. + bne L3A95 branch if valid length. +L3A90 sec indicate not found + rts + +L3A92 lda gbuf+4,x next char +L3A95 cmp pathbuf,y + bne L3A90 if not the same. + inx check next char + iny + dec namcnt + bpl L3A92 if more to compare. + + clc match found + rts + +logvcb ldx vcbptr previously logged in volume? + lda vcbbuf,x (acc = 0?) + beq logvcb1 no, go prepare vcb. + jsr cmpvcb does vcb match vol read? + bcc L3B05 yes, do not disturb. +logvcb1 ldy #$1F zero out vcb entry + +L3AB2 stz vcbbuf,x + inx + dey + bpl L3AB2 + + jsr tstsos make sure it's an xdos disk + bcs L3B05 if not, return carry set. + + jsr tstdupvol does a duplicate with open files + bcs L3B04 already exist? branch if yes. + + lda gbuf+4 move volume name to vcb. + and #$0F strip root marker + tay + pha + ora vcbptr + tax +L3ACE lda gbuf+4,y + sta vcbbuf,x + dex + dey + bne L3ACE + pla get length again + sta vcbbuf,x and save. + lda devnum last device used. + sta vcbbuf+16,x save device # and + lda gbuf+41 total # of blocks on this unit. + sta vcbbuf+18,x + lda gbuf+42 + sta vcbbuf+19,x + lda bloknml save address of root directory. + sta vcbbuf+22,x + lda bloknml+1 + sta vcbbuf+23,x + lda gbuf+39 save address of the 1st bitmap. + sta vcbbuf+26,x + lda gbuf+40 + sta vcbbuf+27,x +L3B04 clc indicate logged if possible +L3B05 rts + +cmpvcb lda gbuf+4 with name in directory. + and #$0F + cmp vcbbuf,x are they the same length? + stx xvcbptr (see rev note #23) + bne L3B1E if not the same. + tay + ora xvcbptr + tax +L3B18 lda gbuf+4,y + cmp vcbbuf,x +L3B1E sec anticipate different names. + bne L3B26 if not the same. + dex + dey + bne L3B18 + clc indicate match. +L3B26 ldx xvcbptr offset to start of vcb (rev note #23) + rts +tstdupvol lda #$00 check for other logged in volumes with the same name. +L3B2C tax + jsr cmpvcb + bcs L3B41 if no match. + lda vcbbuf+17,x test for any open files. + bmi L3B4B cannot look at this volume. + lda #$00 take duplicate offline if no open files + sta vcbbuf,x + sta vcbbuf+16,x + beq L3B49 ok to log in new volume. +L3B41 txa index to next vcb + clc + and #$E0 strip odd stuff. + adc #$20 inc to next entry. + bcc L3B2C branch if more to check +L3B49 clc + rts +L3B4B sta duplflag duplicate has been found. + stx vcbentry save pointer to conflicting vcb. + sec error. + rts + +tstfrblk ldx vcbptr test if enough free blocks available for request. + lda vcbbuf+21,x check if proper count for this volume. + ora vcbbuf+20,x + bne L3BAD branch if count is non-zero. + +tkfrecnt jsr cntbms get # of bitmaps + sta bmcnt and save. + stz scrtch start count at 0 + stz scrtch+1 + lda #$FF mark 'first free' temp as unknown + sta nofree + jsr upbmap update volume bitmap. + bcs L3BC1 if error. + ldx vcbptr get address of 1st bitmap + lda vcbbuf+26,x + sta bloknml + lda vcbbuf+27,x + sta bloknml+1 +L3B81 jsr rdgbuf use general buffer for temp space to + bcs L3BC1 count free blocks (bits). + jsr count + dec bmcnt was that the last bitmap? + bmi L3B96 if so, go change fcb so not done again. + inc bloknml + bne L3B81 + inc bloknml+1 + bra L3B81 +L3B96 ldx vcbptr mark which block had 1st free space + lda nofree + bmi L3BBE if no free space was found. + sta vcbbuf+28,x update the free count. + lda scrtch+1 sta vcbbuf+21,x update volume control byte. + lda scrtch + sta vcbbuf+20,x +L3BAD lda vcbbuf+20,x compare total available free blocks + sec on this volume. + sbc reql + lda vcbbuf+21,x + sbc reqh + bcc L3BBE + clc + rts + +L3BBE lda #MLI.E.VOLFULL + sec +L3BC1 rts + +count ldy #$00 + +L3BC4 lda gbuf,y bit pattern. + beq L3BCC don't count + jsr cntfree +L3BCC lda gbuf+$100,y do both pages with same loop + beq L3BD4 + jsr cntfree +L3BD4 iny + bne L3BC4 loop until all 512 bytes counted. + bit nofree has 1st block w/free space been found? + bpl L3BEE if yes. + lda scrtch test to see if any blocks were counted + ora scrtch+1 + beq L3BEE branch if none counted. + jsr cntbms get total # of maps. + sec subtract countdown from total bitmaps + sbc bmcnt + sta nofree +L3BEE rts + +cntfree asl count the # of bits in this byte + bcc L3BFA + inc scrtch + bne L3BFA + inc scrtch+1 +L3BFA ora #$00 + bne cntfree loop until all bits counted + rts +cntbms ldx vcbptr + ldy vcbbuf+19,x return the # of bitmaps + lda vcbbuf+18,x possible with the total count + bne L3C0B found in the vcb. + dey adj for bitmap block boundary +L3C0B tya + lsr divide by 16. the result is + lsr the # of bitmaps. + lsr + lsr + rts +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.XDOS.B +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.XDOS.C.txt b/ProDOS.FX/ProDOS.S.XDOS.C.txt new file mode 100644 index 00000000..8d0dea8a --- /dev/null +++ b/ProDOS.FX/ProDOS.S.XDOS.C.txt @@ -0,0 +1,720 @@ +NEW + AUTO 3,1 + +* deallocate a block's entry in bitmap +* on entry, x,a = address of block + +dealloc stx bmcnt high address of block. + pha save low address. + ldx vcbptr check that bitmap block address is + lda vcbbuf+19,x valid given the total # of blocks + cmp bmcnt on the volume. + pla + bcc L3C8C branch if invalid + tax + and #$07 bit to be or'd in + tay + lda whichbit,y (shifting takes 7 bytes, but is slower) + sta nofree save bit pattern. + txa low block address. + lsr bmcnt + ror get pointer to byte in block that + lsr bmcnt represents the block address. + ror + lsr bmcnt + ror + sta bmptr save pointer. + lsr bmcnt transfer bit which is page of bitmap + rol half + jsr fndbmap make sure device is correct one. + bcs L3C8B error. + lda bmacmap current map. + cmp bmcnt is in-core bitmap the correct one ? + beq L3C64 branch if yes. + jsr upbmap put current map away. + bcs L3C8B error. + lda bmcnt get map # + ldx vcbptr + sta vcbbuf+28,x and make it current. + lda bmadev + jsr gtbmap read it into buffer + bcs L3C8B +L3C64 ldy bmptr index to byte + lsr half + lda nofree (get indiviual bit) + bcc bmbufhi branch if on page 1 of bitmap + ora bmbuf+$100,y + sta bmbuf+$100,y + bcs L3C7D always. +bmbufhi ora bmbuf,y this address + 2 is used as an absolute reference to bmbuf high byte. + sta bmbuf,y +L3C7D lda #$80 mark bitmap as modified + tsb bmastat + inc deblock inc count of blocks deallocated + bne L3C8A + inc deblock+1 +L3C8A clc +L3C8B rts +L3C8C lda #$5A bitmap block # impossible. + sec bitmap disk address wrong + rts (maybe data masquerading as indx block) + +alc1blk jsr fndbmap get address of bitmap. + bcs L3CB8 error. +L3C95 ldy #$00 begin search at start of bitmap block. + sty half which half (page) to search +L3C9A lda bmbuf,y + bne L3CB9 free blocks indicated by 'on' bits + iny + bne L3C9A check all in 1st page. + inc half now search page 2. + inc basval base value = base address / 2048. +L3CA8 lda bmbuf+$100,y search 2nd half for free block + bne L3CB9 + iny + bne L3CA8 + inc basval add 2048 offset for next page. + jsr nxtbmap get next bitmap (if exists) and + bcc L3C95 update vcb. branch if no error. +L3CB8 rts return error. +L3CB9 sty bmptr save index pointer to valid bit group. + lda basval prep for block address calculation + sta scrtch+1 + tya address of bit pattern. + asl multiply this and basval by 8 + rol scrtch+1 + asl + rol scrtch+1 + asl + rol scrtch+1 + tax low address within 7 of actual address + sec + lda half + beq L3CDB branch if allocating from 1st half. + lda bmbuf+$100,y get pattern from 2nd page. + bcs L3CDE always. +L3CDB lda bmbuf,y get bit pattern from 1st page. +L3CDE rol find left most 'on' bit + bcs L3CE4 if found. + inx adjust low address. + bne L3CDE always. +L3CE4 lsr restore pos'n of all but left most bit. + bcc L3CE4 loop until mark moves into carry. + stx scrtch save low address. + ldx half which half of bitmap ? + bne L3CF4 if page 2. + sta bmbuf,y + beq L3CF7 always. +L3CF4 sta bmbuf+$100,y update to show allocated block in use. +L3CF7 lda #$80 indicate map is modified. + tsb bmastat + ldy vcbptr subtract 1 from total free vcb blocks + lda vcbbuf+20,y to account for newly allocated block. + sbc #$01 (carry is set) + sta vcbbuf+20,y + bcs L3D10 if high free count doesn't need adj. + lda vcbbuf+21,y adjust high count + dec + sta vcbbuf+21,y +L3D10 clc no errors. + lda scrtch return address in y,a of newly + ldy scrtch+1 allocated block. + rts +nxtbmap ldy vcbptr inc to next bitmap, but 1st make sure there is another one. + lda vcbbuf+19,y + lsr + lsr + lsr + lsr + cmp vcbbuf+28,y are there more maps ? + beq L3D60 if no more to look at. + lda vcbbuf+28,y add 1 to current map + inc + sta vcbbuf+28,y + jsr upbmap +fndbmap ldy vcbptr + lda vcbbuf+16,y get device #. + cmp bmadev does this map match this device ? + beq L3D4A yes. + jsr upbmap otherwise, save other volume's bitmap + bcs L3D5F + ldy vcbptr + lda vcbbuf+16,y + sta bmadev and read in fresh bitmap for this dev. +L3D4A ldy bmastat is it already modified ? + bmi L3D54 yes, return pointer + jsr gtbmap otherwise read in fresh bitmap. + bcs L3D5F if error. +L3D54 ldy vcbptr get relative block # of bitmap. + lda vcbbuf+28,y + asl 2 pages per block + sta basval + clc no errors. +L3D5F rts +L3D60 lda #$48 request can't be filled + sec error + rts +upbmap clc + lda bmastat is current map modified ? + bpl L3D5F no. + jsr wrtbmap update device. + bcs L3D5F if error on writing. + lda #$00 + sta bmastat mark bitmap buffer as free + rts +gtbmap sta bmadev read bitmap specified by dev and vcb. + ldy vcbptr get lowest map # with free blocks in it + lda vcbbuf+28,y + sta bmacmap associate offset with bitmap ctrl block. + clc add this # to the base address of + adc vcbbuf+26,y 1st bitmap and save in bmadadr which + sta bmadadr is address of bitmap to be used. + lda vcbbuf+27,y + adc #$00 + sta bmadadr+1 + lda #$01 read device command +L3D92 sta A4L + lda devnum save current dev # + pha + lda bmadev get bitmap's dev # + sta devnum + lda bmadadr and disk address + sta bloknml + lda bmadadr+1 + sta bloknml+1 + lda bmbufhi+2 address of the buffer (low = 0) + jsr dobitmap + tax error code (if any). + pla restore current dev # + sta devnum + bcc L3DB6 and return it if no error. + txa error code +L3DB6 rts + +rdblk sta bloknml + stx bloknml+1 + jsr rdgbuf + rts +wrtbmap lda #$02 write command. + bne L3D92 always. + +wrtgbuf lda #$02 write command + bne L3DC9 always. + +rdgbuf lda #$01 read command. +L3DC9 sta A4L pass to device handler. + lda /gbuf general buffer. + +dobitmap php no interrupts + sei + sta buf+1 buffer high. + stz buf buffer low (always on page boundary) + stz p8error clear global error code. + lda #$FF indicates reg call made to dev handler + sta ioaccess + lda devnum transfer dev # for dispatcher to + sta unitnum convert to unit #. + jsr dmgr call the driver. + bcs L3DE8 if error. + plp restore interrupts. + clc + rts +L3DE8 plp file i/o error. restore interrupts. + sec + rts + +* get mark command +getmark ldx fcbptr index to open fcb. + ldy #$02 index to user's mark parmeter. +.1 lda fcbbuf+18,x transfer current position + sta (A3L),y to user's parameter list + inx + iny + cpy #$05 transfer 3 bytes + bne .1 + clc + rts +L3DFD lda #$4D invalid position + sec + rts +* set mark command +setmark ldy #$04 index to user's desired position. + ldx fcbptr file's control block index. + inx inc by 2 for index to hi eof + inx + sec indicate comparisons are necessary. +.1 lda (A3L),y move it to 'tpos' + sta tposll-2,y + bcc .2 branch if mark < eof + cmp fcbbuf+21,x + bcc .2 branch if mark qualifies. + bne L3DFD branch if mark > eof (invalid position) + dex +.2 dey move/compare next lower byte of mark. + tya test for all bytes moved/tested. + eor #$01 preserves carry status. + bne .1 branch if more. + +rdposn ldy fcbptr test to see if new position is + lda fcbbuf+19,y within the same (current) data block. + and #$FE + sta scrtch + lda tposlh middle byte of new position + sec + sbc scrtch + sta scrtch + bcc L3E44 branch if < current position. + cmp #$02 must be within 512 bytes of beginning + bcs L3E44 of current position. + lda tposhi make sure within the same 64k. + cmp fcbbuf+20,y + bne L3E44 branch if not. + jmp svmark if so, adj fcb, position ptr and return. +L3E44 lda fcbbuf+7,y determine file type for positioning. + beq L3E50 0 = invalid file type. + cmp #$04 tree class file? + bcc L3E59 yes, go position. + jmp dirmark no, test for dir type. +L3E50 ldy #$A4 clear illegal filetype entry in fcb + sta fcbbuf,y + lda #$43 and report error + sec + rts +L3E59 lda fcbbuf+7,y use storage type as # of index levels + sta levels since 1=seed, 2=sapling, 3=tree. + lda fcbbuf+8,y + and #$40 if previous data was modified then + beq L3E6B disk must be updated. + jsr wfcbdat + bcs L3ED4 if error. +L3E6B ldy fcbptr test to see if current index block + lda fcbbuf+20,y is usable by checking if new + and #$FE position is within 128k of the + sta scrtch beginning of current sapling level + lda tposhi chunk. + sec + sbc scrtch + bcc L3E9D branch if a new index block is needed. + cmp #$02 is new position within 128k of old ? + bcs L3E9D branch if not. + ldx levels is it a seed file ? + dex + bne datlevel no, use current indexes. +L3E89 lda tposlh is new position < 512 ? + lsr + ora tposhi + bne L3EEF no, mark both data and index block as + lda fcbbuf+12,y unallocated. 1st block is only block + sta bloknml and it's data. + lda fcbbuf+13,y high block address. + jmp rnewpos go read in block and set statuses. +L3E9D lda fcbbuf+8,y check to see if previous index block + and #$80 was modified. + beq L3EA9 read in over it if current up to date. + jsr wfcbidx go update index on disk (fcb block addr) + bcs L3ED4 +L3EA9 ldx levels be sure there is a top index + cpx #$03 before reading it... + beq posindex branch if file is a tree. + lda tposhi is new position within range of a + lsr sapling file (less than 128k) ? + php save results + lda #$07 (no level is allocated for new pos'n) + plp restore z-flag. + bne L3F18 go mark all as dummy. + jsr clrstats clr status bits 0,1,2 (index/data/alloc) + dex check for seed + beq L3E89 if seed, check for position < 512. + jsr rfcbfst go get only index block. + bcs L3ED4 if error. + ldy fcbptr save newly loaded index block's address. + lda bloknml + sta fcbbuf+14,y + lda bloknml+1 + sta fcbbuf+15,y + bcc datlevel branch always +L3ED4 rts +posindex jsr clrstats clr all alloc requirements for previous + jsr rfcbfst position. get highest level index block + bcs L3ED4 + lda tposhi then test for a sap level index block + lsr + tay + lda (zpt),y + inc zpt+1 + cmp (zpt),y (both high and low = 0 if no index exists) + bne saplevel + tax are both bytes 0 ? + bne saplevel + dec zpt+1 +L3EEF lda #$03 show neither index or data block alloc'd + bra L3F18 +saplevel sta bloknml read in next lower index block. + lda (zpt),y (high address) + sta bloknml+1 + dec zpt+1 + jsr rfcbidx read in sapling level + bcs L3ED4 +datlevel lda tposhi get block address of data block + lsr + lda tposlh ( if there is one ) + ror + tay + lda (zpt),y data block address low + inc zpt+1 + cmp (zpt),y + bne L3F51 + tax + bne L3F51 + lda #$01 show data block as never been allocated + dec zpt+1 +L3F18 ldy fcbptr set status to show what's missing + ora fcbbuf+8,y + sta fcbbuf+8,y + lsr discard bit that says data block + lsr unallocated because carry indicates if + jsr zipdata index block is invalid and needs to be + bcc svmark zeroed. branch if it doesn't need zeroed + jsr zeroindex zero index block in user's i/o buffer + bra svmark +zeroindex lda #$00 + tay +L3F30 sta (zpt),y zero out the index half of the user's + iny i/o buffer + bne L3F30 + inc zpt+1 +L3F37 sta (zpt),y + iny + bne L3F37 + dec zpt+1 restore proper address + rts +zipdata lda #$00 + tay +L3F42 sta (datptr),y zero out data area + iny + bne L3F42 + inc datptr+1 +L3F49 sta (datptr),y + iny + bne L3F49 + dec datptr+1 + rts +L3F51 sta bloknml get data block of new position + lda (zpt),y (high address) + dec zpt+1 +rnewpos sta bloknml+1 + jsr rfcbdat + bcs L3F86 if error. + jsr clrstats show whole chain is allocated. +svmark ldy fcbptr update position in fcb + iny + iny + ldx #$02 +L3F68 lda fcbbuf+18,y save old mark in case calling routine + sta oldmark,x fails later. + lda tposll,x + sta fcbbuf+18,y + dey + dex move 3 byte position marker + bpl L3F68 + clc set up indirect address to buffer + lda datptr page pointed to by the current + sta sos position marker. + lda tposlh + and #$01 + adc datptr+1 + sta sos+1 +L3F86 rts carry set if error +clrstats ldy fcbptr clear allocation states for data block + lda fcbbuf+8,y and both levels of indexes/ + and #$F8 + sta fcbbuf+8,y indicates that either they exist now + rts or unnecessary for current position. +dirmark cmp #$0D is it a directory ? + beq L3F9C yes... + lda #$4A no, so compatability problem. + jsr GP.P8errv should not have been opened !!! + +L3F9C lda scrtch recover results of previous subtraction. + lsr use difference as counter for how many + sta cntent blocks must be read to get to new pos'n. + lda fcbbuf+19,y test for positive direction + cmp tposlh indicated by carry. + bcc L3FB9 if set, position forward. otherwise, +L3FAB ldy #$00 read directory file in reverse order. + jsr dirpos1 read previous block. + bcs L3FD6 if error. + inc cntent count up to 128. + bpl L3FAB loop if more blocks to pass over. + bmi svmark always. +L3FB9 ldy #$02 position is forward from current. + jsr dirpos1 read next directory block + bcs L3FD6 if error. + dec cntent + bne L3FB9 loop if position not found in this block + beq svmark branch always. +dirpos1 lda (datptr),y get link address of previous or next + sta bloknml directory block. + cmp #$01 test for null byte into carry + iny but first be sure there is a link. + lda (datptr),y get the rest of the link. + bne L3FD8 branch if certain link exists. + bcs L3FD8 was the low part null as well ? + lda #$4C something is wrong with directory file! +L3FD6 sec error. + rts +L3FD8 sta bloknml+1 + +* read file's data block + +rfcbdat lda #$01 read command + sta A4L + ldx #datptr points at address of data buffer. + jsr fileio1 go do file input. + bcs L3FF2 error. + ldy fcbptr + lda bloknml + sta fcbbuf+16,y save block # just read in fcb. + lda bloknml+1 + sta fcbbuf+17,y +L3FF2 rts + +rfcbidx lda #$01 prepare to read index block : read command + sta A4L + ldx #$48 address of current index buffer. + jsr fileio1 go read index block. + bcs L400C error + ldy fcbptr + lda bloknml + sta fcbbuf+14,y save block address of this index in fcb + lda bloknml+1 + sta fcbbuf+15,y + clc +L400C rts +L400D lda #$02 write command + .HS 2C skip next instruction + +rfcbfst lda #$01 read command. + pha save the command + lda #$0C + ora fcbptr add offset to fcbptr + tay + pla + ldx #$48 rd block into index portion of file buf + +dofileio sta A4L command + lda fcbbuf,y get disk block address from fcb. + sta bloknml block 0 not legal + cmp fcbbuf+1,y + bne L4031 + cmp #$00 are both bytes 0 ? + bne L4031 no, continue request + lda #$0C otherwise, allocation error. + jsr sysdeath doesn't return... +L4031 lda fcbbuf+1,y high address of disk block + sta bloknml+1 + +fileio1 php no interrupts + sei + lda $00,x get memory address of buffer from + sta buf page zero pointed to by x register + lda $01,x + sta buf+1 and pass address to device handler + ldy fcbptr + lda fcbbuf+1,y + sta devnum along with device #. + lda #$FF also, set to indicate reg call made to + sta ioaccess device handler. + lda devnum transfer device # for dispatcher + sta unitnum to convert to unit #. + stz p8error clear global error code. + jsr dmgr call the driver. + bcs L405E if error. + plp restore interrupts + clc + rts +L405E plp restore interrupts + sec + rts +wfcbfst jsr upbmap update the bitmap + bra L400D and write file's 1st block. +wfcbdat ldx #datptr point at memory address with x and + lda #$10 disk address with y. + ora fcbptr add offset to fcbptr + tay and put in y. + lda #$02 write data block. + jsr dofileio + bcs L4096 if errors. + lda #$BF mark data status as current. + bra L408D +wfcbidx jsr upbmap update bitmap. + ldx #$48 point to address of index buffer + lda #$0E and block address of that index block. + ora fcbptr + tay + lda #$02 + jsr dofileio go write out index block. + bcs L4096 if errors. + lda #$7F mark index status as current. +L408D ldy fcbptr change status byte to reflect + and fcbbuf+8,y successful disk file update. + sta fcbbuf+8,y (carry is unaffected) +L4096 rts + +openf jsr findfile look up the file. + bcc L40A0 if ok. + cmp #$40 is this opening a root directory ? + bne L40A7 if not, then error. +L40A0 jsr tstopen are any other files writing to this + bcc L40AD same file ? branch if not. +L40A5 lda #$50 file is busy, shared access not allowed. +L40A7 sec + rts +L40A9 lda #$4B file is wrong storage type. + sec + rts +L40AD ldy fcbptr get address of 1st free fcb found. + lda fcbflg if this byte <> 0 then free fcb found + bne L40B9 and available for use. + lda #$42 fcb full error. + sec + rts +L40B9 ldx #$1F assign fcb, + lda #$00 but clean it first. +L40BD sta fcbbuf,y + iny + dex + bpl L40BD + lda #$06 start claiming it by moving in file info + tax using x as source index + ora fcbptr and y as destination (fcb). + tay +L40CB lda d_dev-1,x move ownership info. + sta fcbbuf,y note: this code depends upon the defined + dey order of both the fcb and directory + dex entry buffer. + bne L40CB + lda d_stor get storage type and + lsr strip off file name length + lsr by dividing by 16. + lsr + lsr + tax save in x for later comparison + sta fcbbuf+7,y and in fcb for future access. + lda d_attr get file's attributes and use it + and #$03 as a default access request. + cpx #$0D if directory, don't allow write enable. + bne L40EB + and #$01 read enabled bit +L40EB sta fcbbuf+9,y + and #$02 check for write enabled request. + beq L40F7 branch for open as read-only + lda totent otherwise, be sure no one else is + bne L40A5 reading the same file. branch if busy. +L40F7 cpx #$04 is it a tree file type ? + bcc L40FF yes. + cpx #$0D is it a directory type ? + bne L40A9 if not, wrong storage type. +L40FF ldx #$06 move address of 1st block of file, end +L4101 sta bloknml+1 of file and current usage count. + lda fcbptr + ora ofcbtbl,x this is done via a translation table + tay between directory info and fcb. + lda d_frst,x + sta fcbbuf,y + dex + bpl L4101 last loop stores hi address of 1st block + sta bloknml and this is the low one. + ldy fcbptr + lda cntent this was set up by 'tstopen'. + sta fcbbuf,y claim fcb for this file. + jsr alcbuffr go allocate buffer in memory tables. + bcs L4147 if errors. + jsr fndfcbuf rtn addr of bufs in data & index ptrs. + lda flevel mark level at which + sta fcbbuf+27,y file was opened. + lda fcbbuf+7,y file must be positioned at beginning. + cmp #$04 is it a tree file ? + bcs L415E no, assume a directory. + lda #$FF fool the position routine into giving + sta fcbbuf+20,y a valid position with preloaded data, + ldy #$02 etc. set desired position to 0. + lda #$00 +L413C sta tposll,y + dey + bpl L413C + jsr rdposn let tree position routine do the rest. + bcc L4163 if successful. +L4147 pha save error code. + ldy fcbptr free buffer space. + lda fcbbuf+11,y + beq L4156 if no bufnum, ok because never alloc'd. + jsr relbuffr go release buffer. + ldy fcbptr since error was before file was +L4156 lda #$00 successfully opened, then it is + sta fcbbuf,y necessary to release fcb also. + pla error code. + sec + rts +L415E jsr rfcbdat read in 1st block of directory file. + bcs L4147 return error after freeing buffer & fcb. +L4163 ldx vcbptr index to vcb. + inc vcbbuf+30,x add 1 to # of files currently open + lda vcbbuf+17,x and indicate that this volume has at + ora #$80 least 1 file active. + sta vcbbuf+17,x + ldy fcbptr index to fcb. + lda fcbbuf,y return ref # to user. + ldy #$05 + sta (A3L),y + clc open is successful + rts + +* test open +* is there an open file? + +tstopen lda #$00 + sta cntent returns the ref # of a free fcb. + sta totent flag to indicate file already open. + sta fcbflg flag indicates a free fcb is available. +L4188 tay index to next fcb. + ldx fcbflg test for free fcb found. + bne L4191 if already found. + inc cntent +L4191 lda fcbbuf,y is this fcb in use ? + bne L41A3 yes. + txa if not, should we claim it ? + bne L41C1 branch if free fcb already found. + sty fcbptr save index to new free fcb. + lda #$FF set fcb flag to indicate + sta fcbflg free fcb found. + bne L41C1 branch always to test next fcb. +L41A3 tya add offset to index to ownership info + ora #$06 + tay and put it back in y. + ldx #$06 index to directory entry owner info. +L41A9 lda fcbbuf,y all bytes must match to say that it's + cmp d_dev-1,x the same file again. + bne L41C1 if not, then next fcb. + dey index to next lower bytes. + dex + bne L41A9 loop to check all owner info. + inc totent file is already open, now see + lda fcbbuf+9,y if it's already opened for write. and #$02 if so report file busy (with carry set). + and #$02 if so report file busy (with carry set). + beq L41C1 branch if this file is read access only. + sec + rts +L41C1 tya calc position of next fcb. + and #$E0 first strip any possible index offsets. + clc + adc #$20 inc to next fcb. + bne L4188 branch if more to compare. + clc report no conflicts. + rts + + +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.XDOS.C +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.XDOS.D.txt b/ProDOS.FX/ProDOS.S.XDOS.D.txt new file mode 100644 index 00000000..6ec97ada --- /dev/null +++ b/ProDOS.FX/ProDOS.S.XDOS.D.txt @@ -0,0 +1,576 @@ +NEW + AUTO 3,1 + +* read command + +readf jsr mvdbufr xfer buffer address and request count + jsr mvcbytes to a more accessable location, also + pha get fcb attributes and save on stack. + jsr calcmrk calc mark after read, test if mark > eof + pla carry set means end mark > eof. + and #$01 test for read enabled. + bne L41DE branch if ok to read. + lda #$4E illegal access. + bne L4202 always. +L41DE bcc L4205 branch if result mark < eof. adjust + ldy fcbptr request to read until just before eof. + lda fcbbuf+21,y result = (eof-1) - position + sbc tposll + sta cbytes + sta rwreql + lda fcbbuf+22,y + sbc tposlh + sta cbytes+1 + sta rwreqh + ora cbytes if both bytes = 0 then eof error + bne L4210 + lda #$4C eof error +L4202 jmp errfix1 +L4205 lda cbytes + ora cbytes+1 + bne L4210 if read request definitely non-zero. +L420D jmp rwdone do nothing. +L4210 jsr valdbuf validate user's data buffer range. + bcs L4202 branch if memory conflict. + jsr gfcbstyp get storage type + cmp #$04 and find out if it's a tree or other. + bcc L421F branch if a tree file + jmp dread otherwise assume it's a directory. +L421F jsr rdposn set up data pointer. + bcs L4202 errors. + jsr preprw test for newline, setup for partial + jsr readpart read. move current data buffer contents + bvs L420D to user area. branch if satisfied. + bcs L421F indicates newline is set. + lda rwreqh how many blocks are to be read ? + lsr if < 2 then use the slow way. + beq L421F + sta cmdtemp save bulk block count. + jsr gfcbstat make sure current data area doesn't + and #$40 need writing before resetting ptr to + bne L421F read into user's area. branch if data + sta ioaccess needs to be written to force 1st call + lda usrbuf thru all dev handler checking. make + sta datptr the data buffer the user's space. + lda usrbuf+1 + sta datptr+1 +L4249 jsr rdposn get next block directly into user space. + bcs L42B7 if error. +L424E inc datptr+1 incll ptrs by one block (512 bytes) + inc datptr+1 + dec rwreqh + dec rwreqh + inc tposlh + inc tposlh + bne L4269 if pos'n doesn't get to a 64k boundary + inc tposhi otherwise, must check for a 128k one. + lda tposhi carry set if 128k boundary reached. + eor #$01 + lsr +L4269 dec cmdtemp has all been read fast ? + bne L427B branch if more to read. + jsr fxdatptr go fix up data pointer to xdos buffer. + lda rwreql test for end of read. + ora rwreqh are both 0 ? + beq rwdone yes, done. + bne L421F no, read last partial block +L427B bcs L4249 + lda tposhi get index to next block address + lsr + lda tposlh + ror + tay index to address = int(pos/512) + lda (zpt),y get low address + sta bloknml + inc zpt+1 + cmp (zpt),y are hi and low address the same? + bne L4299 no, it's a real block address. + cmp #$00 are both bytes 0 ? + bne L4299 no, must be real data. + sta ioaccess don't do repeat io just after sparse. + beq L429C branch always (carry set). +L4299 lda (zpt),y get high address + clc +L429C dec zpt+1 + bcs L4249 if no block to read. + sta bloknml+1 + lda ioaccess has 1st call gone to device yet ? + beq L4249 no, go thru normal route + clc + php interrupts can't occur during dmgr call + sei + lda datptr+1 reset hi buffer address for dev handler + sta buf+1 + jsr dmgr + bcs L42B6 if error + plp + bcc L424E no errors, branch always. +L42B6 plp restore interrupts. +L42B7 pha save error code. + jsr fxdatptr go restore data pointers, etc. + pla +errfix1 pha save error code + jsr rwdone pass back # of bytes actually read + pla + sec error + rts +rwdone ldy #$06 return total # of bytes actually read + sec derived from cbytes-rwreq. + lda cbytes + sbc rwreql + sta (A3L),y + iny + lda cbytes+1 + sbc rwreqh + sta (A3L),y + jmp rdposn leave with valid position in fcb. + +preprw ldy fcbptr adj pointer to user's buffer to make + sec the transfer + lda usrbuf + sbc tposll + sta usrbuf + bcs L42E9 if no adjustment to hi address needed + dec usrbuf+1 +L42E9 lda fcbbuf+31,y test for new line enabled. + clc + beq L42F9 if new line not enabled. + sec carry indicates new line enabled + sta nlmask + lda fcbbuf+10,y move newline character to more + sta nlchar accesible spot. +L42F9 ldy tposll index to 1st data. + lda datptr reset low order of position pointer to + sta sos beginning of page. + ldx rwreql get low order count of requested bytes. + rts return statuses. +readpart txa x = low count of bytes to move. + bne L430F branch if request is not an even page. + lda rwreqh a call of 0 bytes should never get here! + beq L435D branch if nothing to do. + dec rwreqh +L430F dex +L4310 lda (sos),y move data to user's buffer + sta (usrbuf),y + bcs tstnewl test for newline 1st ! +L4316 txa note: x must be unchanged from tstnewl ! + beq L4332 go see if read request is satified... +L4319 dex dec # of bytes left to move. + iny page crossed ? + bne L4310 no, move next byte. + lda sos+1 test for end of buffer, but first + inc usrbuf+1 adjust user buffer pointer + inc tposlh and position + bne L4329 + inc tposhi +L4329 inc sos+1 and sos buffer high address. + eor datptr+1 (carry is undisturbed) + beq L4310 branch if more to read in buffer. + clv indicate not finished. + bvc L4360 always. +L4332 lda rwreqh + beq L4350 branch if request is satisfied. + iny done with this block of data ? + bne L4340 no, adjust high byte of request. + lda sos+1 maybe, check for end of block buffer. + eor datptr+1 (don't disturb carry). + bne L4343 if hi count can be dealt with next time +L4340 dec rwreqh +L4343 dey restore proper value + bra L4319 +tstnewl lda (sos),y get last byte transferred again. + and nlmask only bits on in mask are significant. + eor nlchar does it match newline character? + bne L4316 no, read next. +L4350 iny adjust position. + bne L435D + inc usrbuf+1 inc pointers + inc tposlh + bne L435D + inc tposhi +L435D bit setvflg (sets v flag) +L4360 sty tposll save low position + bvs L4366 + inx leave request as +1 for next call +L4366 stx rwreql and remainder of request count. + php save statuses + clc adjust user's low buffer address + tya + adc usrbuf + sta usrbuf + bcc L4374 + inc usrbuf+1 adjust hi address as needed. +L4374 plp restore return statuses. +setvflg rts this byte ($60) is used to set v flag. + +fxdatptr lda datptr put current user buffer address back to normal + sta usrbuf + lda datptr+1 + sta usrbuf+1 bank pair byte should be moved also. + ldy fcbptr restore buffer address + jmp fndfcbuf + +* read directory file + +dread jsr rdposn + bcs L43B8 pass back any errors. + jsr preprw prepare for transfer. + jsr readpart move data to user's buffer. + bvc dread repeat until request is satisfied. + jsr rwdone update fcb as to new position. + bcc L43B6 branch if done with no errors. + cmp #$4C was last read to end of file ? + sec anticipate some other error. + bne L43B7 branch if not eof error. + jsr svmark + jsr zipdata clear out data block. + ldy #$00 provide dummy back pointer for future + ldx fcbptr re-position. x = hi byte of last block +L43A6 lda fcbbuf+16,x + sta (datptr),y + lda #$00 mark current block as impossible + sta fcbbuf+16,x + inx + iny inc indexes to do both hi and low bytes + cpy #$02 + bne L43A6 +L43B6 clc no error +L43B7 rts +L43B8 jmp errfix1 report how much xfer'd before error. +mvcbytes ldy #$04 move request count to a more accessable location + lda (A3L),y + sta cbytes + sta rwreql + iny + lda (A3L),y + sta cbytes+1 + sta rwreqh + ldy fcbptr return y = val(fcbptr), + lda fcbbuf+9,y a = attributes + clc and carry clear... + rts +mvdbufr ldy #$02 move the pointer to user's buffer + lda (A3L),y to the block file manager + sta usrbuf z-page area + iny + lda (A3L),y + sta usrbuf+1 +gfcbstyp ldy fcbptr return storage type + lda fcbbuf+7,y + rts + +* this subroutine adds the requested byte count to mark and returns sum +* in scrtch and also returns mark in tpos and oldmark. +* +* on exit: +* y,x,a is unknown +* carry set indicates scrtch > eof + +calcmrk ldx #$00 + ldy fcbptr + clc +L43EE lda fcbbuf+18,y + sta tposll,x + sta oldmark,x + adc cbytes,x + sta scrtch,x + txa + eor #$02 cbytes+2 always=0 + beq eoftest + iny + inx + bne L43EE always. + +eoftest lda scrtch,x new mark in scrtch. + cmp fcbbuf+21,y is new position > eof ? + bcc L4414 no, proceed. + bne L4414 yes, adjust 'cbytes' request + dey + dex all tree bytes compared ? + bpl eoftest no, test next lowest +L4414 rts + +werreof jsr plus2fcb reset eof to pre-error position. +L4418 lda oldeof,x place oldeof back into fcb + sta fcbbuf+21,y + lda oldmark,x also reset mark to last best + sta fcbbuf+18,y write position + sta scrtch,x and copy mark to scrtch for test of + dey eof less than mark. + dex + bpl L4418 + jsr plus2fcb get pointers to test eof < mark. + jsr eoftest carry set means mark > eof !! + +* drop into wadjeof to adjust eof to mark if necessary + +wadjeof jsr plus2fcb get y=fcbptr+2, x=2, a=y. +L4434 lda fcbbuf+21,y copy eof to old eof + sta oldeof,x + bcc L4442 and if carry set... + lda scrtch,x then copy scrtch to fcb's eof. + sta fcbbuf+21,y +L4442 dey + dex copy all 3 bytes + bpl L4434 + rts +plus2fcb lda #$02 on exit both a and y = fcbptr+2. + tax x = 2 + ora fcbptr + tay + rts + +* write command + +writef jsr mvcbytes first determine if requested write is legal. + pha + jsr calcmrk save a copy of eof to old eof, set/clr + jsr wadjeof carry to determine if new mark > eof. + pla get attributes again. + and #$02 is write enabled ? + bne L4462 yes, continue... +L445E lda #$4E illegal access error. + bne L44A2 +L4462 jsr tstwprot otherwise, make sure device is not + bcs L44A2 write protected. if so, branch to abort. + lda cbytes + ora cbytes+1 anything to write ? + bne L4472 branch if so, + jmp rwdone else do nothing. +L4472 jsr mvdbufr move the user's buffer ptr to bfm zero + cmp #$04 page area, also get storage type. + bcs L445E if not tree, return an access error. +L4479 jsr rdposn + bcs L44A2 + jsr gfcbstat + and #$07 + beq L44E9 + ldy #$00 is enough disk space available for +L4487 iny indexes and data block ? + lsr + bne L4487 + sty reql + sta reqh + jsr tstfrblk + bcs L44A2 pass back any errors. + jsr gfcbstat now get more specific. + and #$04 are we lacking a tree top ? + beq L44AC no, test for lack of sapling level index + jsr topdown go allocate tree top and adj file type. + bcc L44B8 continue with allocation of data block. +L44A2 pha save error. + jsr errfix1 error return. + jsr werreof adjust eof and mark to pre-error state. + pla restore error code. + sec + rts +L44AC jsr gfcbstat get status byte again. + and #$02 do we need a sapling level index block ? + beq L44B8 no, assume it's just a data block needed + jsr sapdown go alloc an indx blk and update tree top + bcs L44A2 if error. +L44B8 jsr alcwblk go allocate for data block. + bcs L44A2 + jsr gfcbstat clear allocation required bits in status + ora #$80 but first indicate index block is dirty. + and #$F8 + sta fcbbuf+8,y + lda tposhi calculate position within index block. + lsr + lda tposlh + ror + tay now put block address into index block. + inc zpt+1 high byte first. + lda scrtch+1 + tax + sta (zpt),y + dec zpt+1 restore pointer to lower page of index + lda scrtch block. get low block address. + sta (zpt),y store low address. + ldy fcbptr update fcb to indicate that this block + sta fcbbuf+16,y is allocated. + txa get high address again. + sta fcbbuf+17,y +L44E9 jsr preprw + jsr wrtpart + bvc L4479 + jmp rwdone update fcb with new position + +wrtpart txa + bne L44FF branch if request is not even pages + lda rwreqh a call of 0 bytes should never get here! + beq L4546 do nothing + dec rwreqh +L44FF dex + lda (usrbuf),y move data from user's buffer + sta (sos),y + txa + beq L4525 +L4507 iny page crossed ? + bne L44FF no, keep moving. + lda sos+1 test for end of buffer + inc usrbuf+1 but first adjust user buffer pointer + inc tposlh and position + bne L451C + inc tposhi + bne L451C + lda #$4D out of range if > 32MB + bne L44A2 +L451C inc sos+1 adjust sos buffer high address + eor datptr+1 (carry is undisturbed) + beq L44FF branch if more to write to buffer. + clv indicates not finished. + bvc L4549 always. +L4525 lda rwreqh + beq L4539 branch if request satisfied. + iny done with this block of data ? + bne L4533 if not. + lda sos+1 this is necessary for proper + eor datptr+1 adjustment of request count + bne L4536 +L4533 dec rwreqh +L4536 dey reset modified y + bra L4507 +L4539 iny and position + bne L4546 + inc usrbuf+1 inc pointers + inc tposlh + bne L4546 + inc tposhi +L4546 bit setvflg set v flag +L4549 sty tposll save low position + stx rwreql and remainder of request count. + php save statuses + jsr gfcbstat + ora #$50 + sta fcbbuf+8,y + clc adjust user's low buffer address + lda tposll + adc usrbuf + sta usrbuf + bcc L4564 + inc usrbuf+1 adjust high address as needed. +L4564 jsr fcbused set directory flush bit. + plp restore return statuses + rts +topdown jsr swapdown make current 1st block an entry in new + bcs L45B1 top. branch if errors. + jsr gfcbstyp get storage type + +* has storage type been changed to 'tree' ? if not, assume it was originally +* a seed and both levels need to be built. otherwise, only an index needs +* to be allocated. + + cmp #$03 tree type + beq L457A + jsr swapdown make previous swap a sap level index + bcs L45B1 block. branch if errors. +L457A jsr alcwblk get another block address for the sap + bcs L45B1 level index. branch if errors. + lda tposhi calculate position of new index block + lsr in the top of the tree. + tay + lda scrtch get address of newly allocated index + tax block again. + sta (zpt),y + inc zpt+1 + lda scrtch+1 + sta (zpt),y save hi address + dec zpt+1 + ldy fcbptr make newly allocated block the current + sta fcbbuf+15,y index block. + txa + sta fcbbuf+14,y + jsr wfcbfst save new top of tree + bcs L45B1 + jmp zeroindex zero index block in user's i/o buffer. + +sapdown jsr gfcbstyp find out if dealing with a tree. + cmp #$01 if seed then adj to file type is needed. + beq swapdown branch if seed + jsr rfcbfst otherwise read in top of tree. + bcc L457A if no error. +L45B1 rts return errors. + +swapdown jsr alcwblk make current seed into a sapling, allocate a block before swap. + bcs L45F6 return errors. + ldy fcbptr get previous first block + lda fcbbuf+12,y address into index block. + pha save temporarily while swapping in new + lda scrtch top index. get new block address (low) + tax + sta fcbbuf+12,y + lda fcbbuf+13,y + pha + lda scrtch+1 and high address too + sta fcbbuf+13,y + sta fcbbuf+15,y make new top also the current index in + txa memory. get low address again. + sta fcbbuf+14,y + inc zpt+1 make previous the 1st entry in sub index + pla + sta (zpt) + dec zpt+1 + pla + sta (zpt) + jsr wfcbfst save new file top. + bcs L45F6 if error. + jsr gfcbstyp now adjust storage type by adding 1 + adc #$01 (seed becomes sapling becomes tree) + sta fcbbuf+7,y + lda fcbbuf+8,y mark storage type modified + ora #$08 + sta fcbbuf+8,y + clc no error +L45F6 rts + +alcwblk jsr alc1blk + bcs L4616 + jsr gfcbstat mark usage as modified + ora #$10 + sta fcbbuf+8,y + lda fcbbuf+24,y inc current usage count by 1 + clc + adc #$01 + sta fcbbuf+24,y + lda fcbbuf+25,y + adc #$00 + sta fcbbuf+25,y +L4615 clc no error +L4616 rts + +tstwprot jsr gfcbstat check for 'never been modified' condition + and #$F0 + bne L4615 ordinary rts if known write ok. + lda fcbbuf+1,y get file's dev #. + sta devnum get current status of block device. + +twrprot1 sta unitnum make the device status call + lda bloknml+1 + pha + lda bloknml save the current block values + pha + stz A4L + stz bloknml zero the block # + stz bloknml+1 + php + sei + jsr dmgr + bcs .1 branch if write protect error + lda #$00 otherwise, assume no errors. +.1 plp restore interrupt status + clc + tax save error. + beq .2 branch if no error + sec else, set carry to show error. +.2 pla + sta bloknml restore the block # + pla + sta bloknml+1 + txa + rts carry is indeterminate. + +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.XDOS.D +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.XDOS.E.txt b/ProDOS.FX/ProDOS.S.XDOS.E.txt new file mode 100644 index 00000000..3dc296a3 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.XDOS.E.txt @@ -0,0 +1,603 @@ +NEW + AUTO 3,1 + +* close command + +closef ldy #$01 close all ? + lda (A3L),y + bne L4683 no, just one of them. + sta cferr clear global close error. + lda #$00 start at the beginning. +L4654 sta fcbptr save current low byte of pointer. + tay get the level at which the file + lda fcbbuf+27,y was opened. + cmp flevel if file's level is < global level + bcc L4675 then don't close. + lda fcbbuf,y is this reference file open ? + beq L4675 no, try next. + jsr flush2 clean it out... + bcs L46B6 return flush errors. + jsr close2 update fcb & vcb + ldy #$01 + lda (A3L),y + beq L4675 no error if close all. + bcs L46B6 close error. +L4675 lda fcbptr inc pointer to next fcb + clc + adc #$20 + bcc L4654 branch if within same page. + lda cferr on final close report logged errors. + beq L46B4 branch if errors. + rts (carry already set). +L4683 jsr flush1 flush file 1st (including updating + bcs L46B6 bitmap). branch if errors. + +close2 ldy fcbptr + lda fcbbuf+11,y release file buffer + jsr relbuffr + bcs L46B6 + lda #$00 + ldy fcbptr + sta fcbbuf,y free fcb too + lda fcbbuf+1,y + sta devnum go look for associated vcb + jsr fnddvcb + ldx vcbptr get vcb pointer. + dec vcbbuf+30,x indicate one less file open. + bne L46B4 branch if that wasn't the last... + lda vcbbuf+17,x + and #$7F strip 'files open' bit + sta vcbbuf+17,x +L46B4 clc + rts +L46B6 bcs L46E6 don't report close all error now. + +* flush command + +flushf ldy #$01 flush all ? + lda (A3L),y + bne flush1 no, just one of them. + sta cferr clear global flush error. + lda #$00 start at the beginning. +L46C3 sta fcbptr save current low byte of pointer. + tay index to ref #. + lda fcbbuf,y is this reference file open ? + beq L46D1 no, try next. + jsr flush2 clean it out... + bcs L46E6 return anty errors. +L46D1 lda fcbptr inc pointer to next fcb. + clc + adc #$20 + bcc L46C3 branch if within same page +L46D9 clc + lda cferr on last flush, + beq L46E0 branch if no logged errors. + sec report error now +L46E0 rts + +flush2 jsr fndfcbuf must set up vcb & buffer locations 1st. + bcc L46F1 branch if no error. +L46E6 jmp glberr error so check for close or flush all. + +flush1 stz cferr for normal refnum flush, clear global error. + jsr findfcb setup pointer to fcb user references. + bcs L46E6 return any errors. +L46F1 lda fcbbuf+9,y test to see if file is modified. + and #$02 is it write enabled ? + beq L46D9 branch if 'read only' + lda fcbbuf+28,y has eof been modified ? + bmi L4704 if yes. + jsr gfcbstat has data been modified ? + and #$70 (was written to while it's been open?) + beq L46D9 if not. +L4704 jsr gfcbstat + and #$40 does current data buffer need to be + beq L4710 written ? branch if not. + jsr wfcbdat if so, go write it. + bcs L46E6 if error. +L4710 jsr gfcbstat check to see if the index block (tree + and #$80 files only) needs to be written. + beq L471C branch if not. + jsr wfcbidx + bcs L46E6 return any errors. +L471C lda #$06 prepare to update directory + tax + ora fcbptr + tay +L4723 lda fcbbuf,y note: this code depends on the defined + sta d_dev-1,x order of the file control block and the + dey temporary directory area in 'work space' + dex + bne L4723 + sta devnum + lda d_head read the directory header for this file + ldx d_head+1 + jsr rdblk into the general purpose buffer. + bcs L46E6 if error. + jsr movhed0 move header info. + lda d_entblk get address of directory block that + ldy d_entblk+1 contains the file entry. + cmp d_head test to see if it's the same block the + bne L474E header is in. branch if not. + cpy d_head+1 + beq L4755 branch if header block = entry block +L474E sta bloknml + sty bloknml+1 + jsr rdgbuf get block with file entry in general +L4755 jsr entcalc buffer. set up pointer to entry. + jsr moventry move entry to temp entry buffer in + ldy fcbptr 'work space'. update 'blocks used' count + lda fcbbuf+24,y + sta d_usage + lda fcbbuf+25,y + sta d_usage+1 + ldx #$00 and move in end of file mark whether +L476C lda fcbbuf+21,y needed or not. + sta d_eof,x + inx + cpx #$03 move all 3 bytes + beq L4780 + lda fcbbuf+12,y also move in the address of the file's + sta d_filid,x first block since it might have changed + iny since the file first opened. + bne L476C branch always. +L4780 lda fcbbuf+5,y the last thing to update is storage + asl type (y=fcbptr+2). shift into high + asl nibble. + asl + asl + sta scrtch + lda d_stor get old type byte (might be the same). + and #$0F strip off old type, + ora scrtch add in the new type + sta d_stor and put it away. + jsr drevise go update directory. + bcs glberr error. + ldy fcbptr mark + lda fcbbuf+28,y fcb/directory + and #$7F as + sta fcbbuf+28,y undirty. + lda d_dev see if bitmap should be written. + cmp bmadev is it in same as current file ? + bne L47B2 yes, put it on the disk if necessary. + jsr upbmap go put it away. + bcs glberr flush error +L47B2 clc + rts + +* report error only if not a close all or flush all + +glberr ldy #$01 + pha + lda (A3L),y + bne L47C1 not an 'all' so report now + clc + pla + sta cferr save for later + rts +L47C1 pla + rts +gfcbstat ldy fcbptr index to fcb. + lda fcbbuf+8,y return status byte. + rts +L47CA lda #$4E access error + sec +L47CD rts + +seteof jsr gfcbstyp can only move end of tree, sapling or seed. + cmp #$04 tree type ? + bcs L47CA if not then access error + asl + asl + asl + asl + sta stortyp may be used later. + lda fcbbuf+9,y + and #$02 is write enabled to set new eof ? + beq L47CA no, access error. + jsr tstwprot hardware write protected ? + bcs L47CA yes, access error. + ldy fcbptr save old eof so it can be seen + iny whether blocks need to be released + iny upon contraction. + ldx #$02 all 3 bytes of the eof +L47EF lda fcbbuf+21,y + sta oldeof,x + dey + dex + bpl L47EF + ldy #$04 + ldx #$02 +L47FD lda (A3L),y position mark to new eof + sta tposll,x + dey + dex + bpl L47FD + ldx #$02 point to 3rd byte. +L4808 lda oldeof,x see if eof moved backwards so blocks + cmp tposll,x can be released. + bcc eofset (branch if not) + bne purge branch if blocks to be released + dex + bpl L4808 all 3 bytes +eofset ldy #$04 + ldx fcbptr place new end of file into fcb + inx + inx +L481C lda (A3L),y + sta fcbbuf+21,x + dex + dey + cpy #$02 all 3 bytes moved ? + bcs L481C no. + jmp fcbused mark fcb as dirty. +purge jsr flush1 make sure file is current + bcs L47CD + ldx datptr+1 pointer to index block + inx + inx + stx zpt+1 (zero page conflict with dir buf ptr) + ldx datptr + stx zpt + ldy fcbptr check if eof < mark + iny + iny + ldx #$02 +L4840 lda fcbbuf+18,y + cmp tposll,x compare until not equal or carry clear. + bcc L485F branch if eof > mark. + bne L484E branch if eof < mark. + dey + dex + bpl L4840 compare all 3 bytes +L484E ldy fcbptr + ldx #$00 +L4853 lda tposll,x fake position, correct position will + sta fcbbuf+18,y be made below... + iny + inx + cpx #$03 move all 3 bytes + bne L4853 +L485F jsr tkfrecnt force free block count before releasing + lda tposll blocks. prepare for purge of excess... + sta dseed all blocks and bytes beyond new eof + lda tposlh must be zero'd + sta dsap + and #$01 + sta dseed+1 + lda tposhi + lsr + sta dtree + ror dsap pass position in terms of block & bytes. + lda dseed now adjust for boundaries of $200 + ora dseed+1 + bne L48A2 branch if no adjustment necessary. + lda dsap get correct block ositions for sap + sec and tree levels. + sbc #$01 + sta dsap deallocate for last (phantom) block + lda #$02 and don't modify last data block. + bcs L489F branch if tree level unaffected. + dec dtree + bpl L489F branch if new eof not zero + lda #$00 + sta dtree otherwise, make a null seed out of it. + sta dsap +L489F sta dseed+1 +L48A2 ldy fcbptr also must pass file's 1st block address. + lda fcbbuf+12,y + sta firstbl + lda fcbbuf+13,y + sta firstbh + stz deblock lastly, initialize # of blocks to + stz deblock+1 be free'd. + jsr detree deallocate blocks from tree. + php save any error status until fcb + pha is cleaned up. + sec + ldy fcbptr + ldx #$00 +L48C2 lda firstbl,x + sta fcbbuf+12,y move in possible new first file block + lda fcbbuf+24,y address. adjust usage count also + sbc deblock,x + sta fcbbuf+24,y + iny + inx + txa + and #$01 test for both bytes adjusted + bne L48C2 without disturbing carry. + lda stortyp get possibly modified storage type + lsr + lsr + lsr + lsr + ldy fcbptr and save it in fcb. + sta fcbbuf+7,y + jsr clrstats make it look as though position has + jsr dvcbrev nothing allocated, update total blocks + ldy fcbptr in fcb and correct position. + iny + iny + ldx #$02 +L48F2 lda fcbbuf+18,y tell 'rdposn' to go to correct + sta tposll,x + eor #$80 position from incorrect place. + sta fcbbuf+18,y + dey + dex + bpl L48F2 + jsr rdposn go to correct position. + bcc L490D if no error. + tax otherwise, report latest error. + pla + plp + txa restore latest error code to stack + sec + php + pha save new error. + +* mark file as in need of a flush and update fcb with new end of file, +* then flush it. + +L490D jsr eofset go mark and update + jsr flush1 then go do the flush. + bcc L491C branch if no error. + tax save latest error. + pla clean previous error off stack + plp + txa and restore latest error to stack. + sec show error condition. + php restore error status to stack + pha and the error code. +L491C pla report any errors that may have + plp appeared. + rts + +geteof ldx fcbptr index to end of file mark + ldy #$02 and index to user's call parameters +L4924 lda fcbbuf+21,x + sta (A3L),y + inx + iny + cpy #$05 + bne L4924 loop until all 3 bytes moved + clc no errors + rts + +newline ldy #$02 adjust newline status for open file. + lda (A3L),y on or off ? + ldx fcbptr it will be 0 if off. + sta fcbbuf+31,x set new line mask + iny + lda (A3L),y and move in 'new-line' byte + sta fcbbuf+10,x + clc no error possible + rts + +getinfo jsr findfile look for file. + bcc L4988 no error. + cmp #$40 was it a root directory file ? + sec (in case of no match) + bne L49A4 if not, then error. + lda #$F0 + sta d_stor for get info, report proper storage + stz reql type. forca a count of free blocks. + stz reqh + ldx vcbptr + jsr tkfrecnt get a fresh count of free blocks on + ldx vcbptr this volume. + lda vcbbuf+21,x return total blocks and total in use. + sta reqh 1st transfer 'free' blocks to zpage + lda vcbbuf+20,x for later subtraction to determine + sta reql the 'used' count. + lda vcbbuf+19,x transfer to 'd.' table as aux id + sta d_auxid+1 (total block count is considered aux id + pha for the volume) + lda vcbbuf+18,x + sta d_auxid + sec subtract and report the number of + sbc reql blocks 'in use' + sta d_usage + pla + sbc reqh + sta d_usage+1 +L4988 lda d_stor transfer bytes from internal order to + lsr call spec via 'inftabl' translation + lsr table but first change storage type to + lsr external (low nibble) format. + lsr + sta d_stor + ldy #$11 index to last of user's spec table. +L4994 lda inftabl-3,y + and #$7F strip bit used by setinfo + tax + lda d_stor,x move directory info to call spec. table + sta (A3L),y + dey + cpy #$03 + bcs L4994 if all info bytes moved, retn carry clr +L49A4 rts + +setinfo jsr findfile get the file to work on. + bcs L49CF if error. + lda bubit see if backup bit can be cleared + eor #$20 + and d_attr + and #$20 + sta bkbitflg or preserve current... + ldy #$0D init pointer to user supplied list. +L49B9 ldx inftabl-3,y get index to corresponding 'd.' table. + bmi L49C3 branch if parameter can't be set. + lda (A3L),y + sta d_stor,x +L49C3 dey has user's request been satisfied ? + cpy #$03 + bcs L49B9 no, move next byte. + and #$18 make sure no illegal access bits were + beq L49D0 set !! branch if legal access. + lda #$4E otherwise, access error. + sec +L49CF rts +L49D0 ldy #$0B + lda (A3L),y was clock null input ? + beq L49D9 if yes. + jmp drevise1 end by updating directory. +L49D9 jmp drevise update with clock also... + +rename jsr lookfile look for source (original) file. + bcc L4A1E if found. + cmp #$40 trying to rename a volume ? + bne L49FD no, return error. + jsr renpath syntax new name. + bcs L49FD rename error. + ldy pathbuf find out if only rootname for new name + iny + lda pathbuf,y must be $FF if volume name only. + bne L4A72 if not single name + ldx vcbptr check for open files before changing. + lda vcbbuf+17,x + bpl L49FF if volume not busy. + lda #$50 file busy error. +L49FD sec + rts +L49FF ldy #$00 get newname's length + lda pathbuf,y + ora #$F0 (root file storage type) + jsr mvrotnam update root directory. + bcs L4A74 rename error. + ldy #$00 + ldx vcbptr update vcb also. +L4A10 lda pathbuf,y move new name to vcb. + beq L4A1C + sta vcbbuf,x + iny next character + inx + bne L4A10 always. +L4A1C clc no errors + rts +L4A1E jsr getnamptr set y = 1st char of path, x = 0. +L4A21 lda pathbuf,y move original name to gbuf + sta gbuf,x for later comparison to new name. + bmi L4A2D if last character has been moved + iny otherwise, get the next one. + inx + bne L4A21 always. +L4A2D jsr renpath get new name syntaxed. + bcs L4A74 rename error. + jsr getnamptr set y = path, x = 0. + lda pathbuf,y now compare new name with old name +L4A38 cmp gbuf,x to make sure they are in the same dir. + php save result of comparison. + and #$F0 was last char really a count ? + bne L4A46 if not. + sty rnptr save pointer to next name, it might + stx namptr be the last. +L4A46 plp result of last comparison ? + bne L4A52 branch if different character or count. + inx bump pointers. + iny + lda pathbuf,y was it the last character ? + bne L4A38 if not. + clc no operation, names were the same. + rts +L4A52 ldy rnptr index to last name in the chain. + lda pathbuf,y get last name length. + sec + adc rnptr + tay + lda pathbuf,y this byte should be $00 ! + bne L4A72 if not, bad path error. + ldx namptr index to last of original name + lda gbuf,x + sec + adc namptr + tax + lda gbuf,x this byte should also be $00. + beq L4A76 if so, continue processing. +L4A72 lda #$40 bad pathname error. +L4A74 sec + rts +L4A76 jsr lookfile test for duplicate file name. + bcs L4A7F branch if file not found, which is ok !! + lda #$47 duplicate name error. + sec + rts +L4A7F cmp #$46 was it a valid file not found ? + bne L4A74 no, rename error. + jsr setpath syntax pathname of file to be changed. + jsr findfile get all the info on this file. + bcs L4A74 rename error. + jsr tstopen is file in use ? + lda #$50 anticipate file busy error. + bcs L4A74 error if in use. + lda d_attr test bit which allows rename. + and #$40 + bne L4A9D branch if ok to rename + lda #$4E otherwise, illegal access. +L4A9B sec + rts +L4A9D lda d_stor find out which storage type. + and #$F0 strip off name length. + cmp #$D0 is it a directory ? + beq L4AAE then ok. + cmp #$40 is it a seed, sapling or tree ? + bcc L4AAE then ok. + lda #$4A file incompatible error. + bne L4A9B always. +L4AAE jsr renpath since both names go into the directory, + bcs L4A74 syntax the new name to get the local + ldy rnptr name address. y = index to local name + ldx pathbuf,y length. adj y to last char of new name. tya + tya + adc pathbuf,y + tay +L4ABE lda pathbuf,y move local name to dir entry workspace. + sta d_stor,x + dey + dex + bne L4ABE + lda d_stor preserve file storage type. + and #$F0 strip off old name length. + tax + ora pathbuf,y add in new name's length. + sta d_stor + cpx #$D0 that file must be changed also. + bne L4AF0 branch if not directory type. + lda d_frst read in 1st header block of subdir + ldx d_frst+1 + jsr rdblk + bcs L4A74 errors. + ldy rnptr change the header's name to match the + lda pathbuf,y owner's new name. get local name length. + ora #$E0 assume it's a header. + jsr mvrotnam + bcs L4A74 +L4AF0 jmp drevise1 end by updating all path directories. + +mvrotnam ldx #$00 +L4AF5 sta gbuf+4,x + inx + iny + lda pathbuf,y + bne L4AF5 + jmp wrtgbuf write changed header block. +renpath ldy #$03 get address to new pathname + lda (A3L),y + iny + sta zpt + lda (A3L),y set up for syntaxing routine (synpath) + sta zpt+1 + jmp synpath do syntax (returns y = local namelength) + +getnamptr ldy #$00 return pointer to 1st name of path. + bit prfxflg is this a prefixed name ? + bmi L4B1A branch if not. + ldy newpfxptr +L4B1A ldx #$00 + rts + +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.XDOS.E +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.XDOS.F.txt b/ProDOS.FX/ProDOS.S.XDOS.F.txt new file mode 100644 index 00000000..31fc9bab --- /dev/null +++ b/ProDOS.FX/ProDOS.S.XDOS.F.txt @@ -0,0 +1,765 @@ +NEW + AUTO 3,1 + +destroy jsr findfile look for file to be destroyed. + bcs L4B66 if error. + jsr tstopen is it open ? + lda totent + bne L4B64 error if open. + stz reql force proper free count in volume. + stz reqh (no disk access occurs if already + jsr tstfrblk proper) + bcc L4B39 no errors. + cmp #$48 was error a full disk ? + bne L4B66 no, report error. +L4B39 lda d_attr make sure ok to destroy file. + and #$80 + bne L4B45 branch if ok to destroy. + lda #MLI.E.LOCKED access error + jsr GP.P8errv + +L4B45 lda devnum last device used. + jsr twrprot1 test for write protected hardware + bcs L4B66 before going thru deallocation. + lda d_frst 'detree' needs first block address + sta firstbl + lda d_frst+1 + sta firstbh + lda d_stor find out which storage type. + and #$F0 strip off name length. + cmp #$40 is it a seed, sapling or tree ? + bcc L4B68 branch if it is. + bra L4BCF otherwise, test for directory destroy. +L4B64 lda #$50 file busy error. +L4B66 sec can't be destroyed + rts +L4B68 sta stortyp destroy a tree file. save storage type. + ldx #$05 + lda #$00 set 'detree' input variables, must be +L4B6F sta stortyp,x in order: deblock, dtree, dsap, dseed. + dex + bne L4B6F loop until all zero'd. + lda #$02 this avoids an extra file i/o and pre- + sta dseed+1 vents destruction of any deleted data. + inc delflag don't allow detree to zero index blocks. + jsr detree make trees and saplings into seeds. + dec delflag reset flag. + bcs L4B93 (de-evolution) +L4B85 ldx firstbh + lda firstbl now deallocate seed. + jsr dealloc + bcs L4B93 + jsr upbmap +L4B93 pha save possible error code. + lda #$00 update directory to free entry space. + sta d_stor + cmp h_fcnt file entry wrap ? + bne L4BA1 branch if no carry adjustment. + dec h_fcnt+1 take carry from hi byte of file entries. +L4BA1 dec h_fcnt mark header with one less file. + jsr dvcbrev go update block count in vcb (ignore + jsr drevise error, if any) and update dir last. + tax save possible new error code, + pla restore possible old error code. + bcc L4BAF branch if last call succeeded. + txa last call failed, use it's error code. +L4BAF cmp #$01 adjust carry accordingly + rts +dvcbrev ldy vcbptr update block free count in vcb. point to vcb of correct device. + lda deblock get # of blocks recently freed. + adc vcbbuf+20,y + sta vcbbuf+20,y update current free block count. + lda deblock+1 + adc vcbbuf+21,y + sta vcbbuf+21,y + lda #$00 force re-scan from 1st bitmap + sta vcbbuf+28,y + rts +L4BCD bcc L4B85 branch widened (always taken) +L4BCF cmp #$D0 is this a directory file ? + bne L4C1B no, file incompatible. + jsr fndbmap make sure a buffer available for bitmap + bcs L4C1A if error. + lda d_frst read 1st block of directory into gbuf + sta bloknml + lda d_frst+1 + sta bloknml+1 + jsr rdgbuf + bcs L4C1A + lda gbuf+37 do any files exist in this directory ? + bne L4BF1 if so, access error. + lda gbuf+38 + beq L4BF6 +L4BF1 lda #$4E access error. + jsr GP.P8errv +L4BF6 sta gbuf+4 make it an invalid subdirectory + jsr wrtgbuf + bcs L4C1A +L4BFE lda gbuf+2 get forward link. + cmp #$01 test for null block into carry. + ldx gbuf+3 get the rest of the block address. + bne L4C0A branch if not null. + bcc L4BCD was the low part null as well ? +L4C0A jsr dealloc free this block. + bcs L4C1A + lda gbuf+2 + ldx gbuf+3 + jsr rdblk + bcc L4BFE loop until all freed +L4C1A rts +L4C1B lda #MLI.E.INCFF file incompatible + jsr GP.P8errv + +fcbused pha mark fcb as dirty so the directory will be flushed on 'flush'. + tya save regs. + pha + ldy fcbptr + lda fcbbuf+28,y fetch current fcb dirty byte. + ora #$80 mark fcb as dirty. + sta fcbbuf+28,y save it back + pla and restore regs. + tay + pla + rts + +* 'detree' deallocates blocks from tree files. it is assumed that the device has +* been pre-selected and the 'gbuf' may be used. +* +* on entry: +* stortype = storage type in upper nibble, lower nibble is undisturbed. +* firstbl & firstbh = first block of file (index or data). +* deblock = 0 +* dtree = ptr to 1st block with data to be deallocated at tree level. +* dsap = ptr to 1st block at sapling level. +* dseed = byte (0-511) position to be zeroed from (inclusive). +* +* on exit: +* stortype = modified result of storage type (if applicable). +* firstbl & h = modified if storage type changed. +* deblock = total number of blocks freed at all levels. +* dtree, dsap, deseed unchanged. +* +* to trim a tree to a seed file, both dtree and dsap must be zero. +* to go from tree to sapling, dtree alone must be zero. + +detree lda stortyp which kind of tree ? + cmp #$20 is it a 'seed' ? + bcc L4C46 if yes. + cmp #$30 a sapling ? + bcc L4C51 if yes. + cmp #$40 is it at least a 'tree' ? + bcc L4C59 branch if it is. + lda #$0C block allocation error. + jsr sysdeath P8 system death vector + +* seedling file type - make sure first desireable block is the only +* block available in a seedling file. + +L4C46 lda dsap + ora dtree + bne L4CC2 + jmp seedel0 + +* sapling file type - make sure first desireable block is within the range of +* blocks available in a sapling file + +L4C51 lda dtree can't have any blocks in this range + bne L4CC2 if so then done + jmp sapdel0 else go deallocate +L4C59 lda #$80 + sta topdest for tree top start at end, work backwards. +L4C5E jsr drdfrst read specified first block into gbuf. + bcs L4CC2 return errors. + ldy topdest get current pointer to top indexes. + cpy dtree have enough sapling indexes been + beq L4CC3 deallocated? yes, now deallocate blocks + ldx #$07 buffer up to 8 sapling index block +L4C6D lda gbuf,y addresses. fetch low block address + sta dealbufl,x and save it. + ora gbuf+$100,y is it a real block that is allocated? + beq L4C81 branch if phantom block. + lda gbuf+$100,y fetch high block address + sta dealbufh,x and save it. + dex decrement and test for dealc buf filled. + bmi L4C93 branch if 8 addresses fetched. +L4C81 dey look for end of deallocation limit. + cpy dtree is this the last position on tree level? + bne L4C6D if not. + iny + lda #$00 fill rest of dealc buffer with null addresses. +L4C8A sta dealbufl,x + sta dealbufh,x + dex + bpl L4C8A +L4C93 dey decrement to prepare for next time. + sty topdest save index. + ldx #$07 +L4C99 stx dtmpx save index to dealc buf. + lda dealbufl,x + sta bloknml + ora dealbufh,x finished ? + beq L4C5E branch if done with this level. + lda dealbufh,x complete address with high byte, + sta bloknml+1 + jsr rdgbuf read sapling level into gbuf. + bcs L4CC2 return errors. + jsr dealblk go free all data indexes in this block + bcs L4CC2 + jsr wrtgbuf write the flipped index block + bcs L4CC2 + ldx dtmpx restore index to dealc buff. + dex are there more to free? + bpl L4C99 branch if so. + bmi L4C5E branch always to get up to 8 more +L4CC2 rts sapling block numbers. +L4CC3 ldy dtree deallocate all sapling blocks greater + iny than specified block. + jsr dalblk1 (master index in gbuf) + bcs L4CC2 if errors. + jsr wrtgbuf write updated master index back to disk. + bcs L4CC2 + ldy dtree figure out if tree can become sapling. + beq L4CEB branch if it can. + lda gbuf,y otherwise, continue with partial. + sta bloknml deallocation of last sapling index. + ora gbuf+$100,y is there such a sapling index block ? + beq L4CC2 all done if not. + lda gbuf+$100,y read in sapling level to be modified. + sta bloknml+1 + jsr rdgbuf read highest sapling index into gbuf. + bcc L4CF5 + rts +L4CEB jsr shrink shrink tree to sapling + bcs L4CC2 +sapdel0 jsr drdfrst read specified sapling level index + bcs L4CC2 into gbuf. branch if error. +L4CF5 ldy dsap pointer to last of desirable indexes. + iny inc to 1st undesirable. + beq L4D05 branch if all are desirable. + jsr dalblk1 deallocate all indexes above specified. + bcs L4CC2 + jsr wrtgbuf write out the index block + bcs L4CC2 +L4D05 ldy dsap prepare to clean up last data block. + beq L4D1F branch if possibility of making a seed. +L4D0A lda gbuf,y fetch low order data block address. + sta bloknml + ora gbuf+$100,y is it a real block ? + beq L4CC2 if not, then done. + lda gbuf+$100,y + sta bloknml+1 + jsr rdgbuf go read data block into gbuf. + bcc L4D2E branch if good read + rts or return error. +L4D1F lda dtree are both tree and sap levels zero ? + bne L4D0A if not. + jsr shrink reduce this sap to a seed. + bcs L4D52 if error. +seedel0 jsr drdfrst go read data block. + bcs L4D52 if error. +L4D2E ldy dseed+1 check high byte for no deletion. + beq L4D39 branch if all of 2nd page to be deleted. + dey if dseed > $200 then all were done. + bne L4D52 branch if that is the case. + ldy dseed clear only bytes >= dseed. +L4D39 lda #$00 +L4D3B sta gbuf+$100,y zero out unwanted data + iny + bne L4D3B + ldy dseed+1 is that all ? + bne L4D4F yes. + ldy dseed +L4D49 sta gbuf,y + iny + bne L4D49 +L4D4F jmp wrtgbuf update data block to disk. +L4D52 rts return error status. +drdfrst lda firstbl read specified 1st block into gbuf + ldx firstbh + jmp rdblk go read it + +* beware that dealloc may bring in a new bitmap block and may destroy +* locations 46 and 47 which are used to point to the current index block. + +shrink ldx firstbh first deallocate top index block + txa + pha + lda firstbl + pha save block address of this index block. + jsr dealloc free it from the bitmap + pla + sta bloknml set master of sapling + pla index block address. + sta bloknml+1 + bcs L4D8D report errors. + lda gbuf get # of new 1st block from old index. + sta firstbl + lda gbuf+$100 + sta firstbh + ldy #$00 + jsr swapme flip that one entry in old top index. + sec now change file type, + lda stortyp from tree to sapling, + sbc #$10 or from sapling to seed. + sta stortyp + jsr wrtgbuf write the (deallocated) old top index. +L4D8D rts return error status. +dealblk ldy #$00 start at beginning. +dalblk1 lda bloknml save disk address of gbuf's data. + pha + lda bloknml+1 + pha +L4D96 sty saptr save current index. + lda gbuf,y get low address of block to deallocate. + cmp #$01 test for null block into carry. + ldx gbuf+$100,y get remainder of block address. + bne L4DA5 branch if not null. + bcc L4DB0 was the low part null too ? +L4DA5 jsr dealloc free it up on volume bitmap. + bcs L4DB4 return any error. + ldy saptr get index to sapling level index block. + jsr swapme +L4DB0 iny next block address. + bne L4D96 if more to deallocate or test. + clc no error. +L4DB4 tax save error code, if any. + pla restore blocknm (16 bit) + sta bloknml+1 + pla + sta bloknml + txa restore return code + rts +swapme lda delflag swapping or zeroing ? + bne L4DC5 skip if swapping. + tax make x = 0. + beq L4DCB zero the index (always taken). +L4DC5 ldx gbuf+$100,y index high + lda gbuf,y index low +L4DCB sta gbuf+$100,y save index high + txa + sta gbuf,y save index low + rts done. + +* MEMMGR memory manager +* +* allocate buffer in memory tables + +alcbuffr ldy #$04 index to user specified buffer. +alcbufr1 lda (A3L),y this buffer must be on a page boundary. + tax save for validation. + cmp #$08 + bcc L4E1E cannot be lower than video ! + cmp #$BC nor greater than $BB00 + bcs L4E1E since it would wipe out globals... + sta datptr+1 + dey + lda (A3L),y low address should be zero ! + sta datptr + bne L4E1E error if not page boundary. + inx add 4 pages for 1k buffer. + inx + inx + inx +L4DED dex test for conflicts. + jsr cmembit test for free buffer space + and memmap,y P8 memory bitmap + bne L4E1E report memory conflict, if any. + cpx datptr+1 test all 4 pages. + bne L4DED + inx add 4 pages again for allocation. + inx + inx + inx +L4DFE dex set proper bits to 1 + jsr cmembit + ora memmap,y to mark it's allocation. + sta memmap,y + cpx datptr+1 set all 4 pages + bne L4DFE + ldy fcbptr calculate buffer number + lda fcbbuf,y + asl buffer number = (entnum) * 2. + sta fcbbuf+11,y save it in fcb. + tax use entnum * 2 as index to global + lda datptr+1 buffer addr tables. get addr already + sta buftbl-1,x validated as good. store hi addr + clc (entnums start at 1, not 0) + rts +L4E1E lda #$56 buffer is in use or not legal + sec + rts +getbufadr tax index into global buffer table. + lda buftbl-2,x + sta bufaddrl + lda buftbl-1,x + sta bufaddrh + rts +relbuffr jsr getbufadr preserve buffer address in 'bufaddr' + tay returns high buffer address in acc. + beq L4E54 branch if unallocated buffer space. + stz buftbl-1,x take address out of buffer list. + stz buftbl-2,x (x was set up by getbufadr) +freebuf ldx bufaddrh get hi buffer address + inx add 4 pages to account for 1k space. + inx + inx + inx +L4E43 dex drop to next lower page. + jsr cmembit get bit and position to memtable of + eor #$FF this page. invert mask. + and memmap,y mark address as free space. + sta memmap,y + cpx bufaddrh all pages freed ? + bne L4E43 no. +L4E54 clc no error. + rts + +* calculate memory allocation bit position. +* on entry: x = high address of buffer, low address assumed zero. +* on exit: acc = allocation bit mask, x = unchanged, y = pointer to memtabl byte + +cmembit txa page address + and #$07 which page in any 2k set ? + tay use as index to determine + lda whichbit,y bit position representation. + pha save bit position mask for now. + txa page address. + lsr + lsr determine 2k set + lsr + tay return it in y. + pla restore bit mask. return bit position + rts in a & y, pointer to memtabl in x. +valdbuf lda usrbuf+1 high address of user's buffer + cmp #$02 must be greater than page 2. + bcc L4E1E report bad buffer + ldx cbytes+1 + lda cbytes get cbytes-1 value. + sbc #$01 (carry is set) + bcs L4E76 + dex +L4E76 clc + adc usrbuf calculate end of request address. + txa do high address. + adc usrbuf+1 the final address + tax must be less than $BFnn (globals) + cpx #$BF + bcs L4E1E report bad buffer. + inx loop thru all affected pages. +vldbuf1 dex check next lower page. + jsr cmembit + and memmap,y if 0 then no conflict. + bne L4E1E branch if conflict. + cpx usrbuf+1 was that the last (lowest) page ? + bne vldbuf1 if not. + clc all pages ok. + rts + +getbuf ldy #$02 give user address of file buffer referenced by refnum. + lda bufaddrl + sta (A3L),y + iny + lda bufaddrh + sta (A3L),y + clc no errors possible + rts + +setbuf ldy #$03 + jsr alcbufr1 allocate new buffer address over old one + bcs L4EC7 report any errors immediately + lda bufaddrh + sta usrbuf+1 + lda bufaddrl + sta usrbuf + jsr freebuf free address space of old buffer + ldy #$00 + ldx #$03 +L4EB8 lda (usrbuf),y move all 4 pages of the buffer to + sta (datptr),y new location. + iny + bne L4EB8 + inc datptr+1 + inc usrbuf+1 + dex + bpl L4EB8 + clc no errors +L4EC7 rts + + +* move 3 pages of dispatcher from 'displc2' to 'dispadr' +* this move routine must be resident above $E000 at all times + +calldisp lda RRAMWRAMBNK2 read/write RAM bank 2 + lda RRAMWRAMBNK2 + lda /dispadr + sta A2L+1 + lda #dispadr + sta A2L + lda /displc2 + sta A1L+1 + stz A1L + ldy #$00 + ldx #$03 3 pages to move. +L4EE0 dey move a page of code. + lda (A1L),y + sta (A2L),y + tya + bne L4EE0 + inc A1L+1 pointers to next page + inc A2L+1 + dex move all pages needed + bne L4EE0 + lda RRAMWRAMBNK1 read/write RAM bank 1 + lda RRAMWRAMBNK1 swap mli space back in + stz mliact MLI active flag + stz softev + lda /dispadr point RESET to dispatch entry + sta softev+1 + eor #$A5 + sta pwredup power up byte + jmp dispadr + +* translate a prodos call into a smartport call +* to access unseen smartport devices + +remap_sp ldx #$03 assume 3 parameters. + lda A4L command number + sta cmdnum + bne L4F1B taken if not status call + + ldy #spstatlist set up memory for the status list buffer + sty buf fake up the prodos parameters + ldy /spstatlist + sty buf+1 + stz bloknml set statcode = 0 for simple status call + +L4F1B cmp #$03 format command ? + bne L4F21 no. + ldx #$01 format has only 1 parameter. +L4F21 stx statparms set # of parms. + lda unitnum + lsr turn unit number into an index + lsr + lsr + lsr + tax + lda spunit-1,x get the smartport unit number and + sta sp_unitnum store into smartport parm list. + lda spvectlo-1,x + sta sp_vector+1 copy smartport entry address + lda spvecthi-1,x + sta sp_vector+2 + ldx #$04 copy buffer pointer and block # +L4F3F lda buf-1,x from prodos parameters + sta sp_bufptr-1,x to smartport parameter block + dex + bne L4F3F +sp_vector jsr $0000 smartport call (entry address gets modified) +cmdnum .HS 00 command # + .DA statparms + bcs L4F6E + + ldx cmdnum status call ? + bne L4F6E no... + ldx spstatlist+1 else get the block count + ldy spstatlist+2 + lda spstatlist get the returned status. + bit #$10 is there a disk present ? + bne L4F65 yes, check for write protected. + lda #$2F return offline error. + bra L4F6D +L4F65 and #$44 mask all but write allowed and write + eor #$40 protected bits. if allowed and not + beq L4F6E protected, exit with carry clear + lda #$2B else return write protected error. +L4F6D sec +L4F6E rts +spvectlo .HS 0000000000000000 storage for low byte of smartport entry. + .HS 00000000000000 +spvecthi .HS 0000000000000000 storage for high byte of smartport entry. + .HS 00000000000000 +statparms .HS 03 # of parms (always 3 except format) +sp_unitnum .HS 00 unit number +sp_bufptr .HS 0000 data buffer + .HS 000000 block number (3 bytes) + +* data tables + +scnums .HS D3000000 table of valid mli command numbers. + .HS 40410000808182 + .HS 65C0C1C2C3C4C5C6 + .HS C7C8C9CACBCCCDCE + .HS CF00D0D1D2 +pcntbl .HS 02FFFFFF parameter counts for the calls + .HS 0201FFFF030300 + .HS 04070102070A0201 + .HS 0103030404010102 + .HS 02FF020202 + +* command table + +cmdtable .DA create + .DA destroy + .DA rename + .DA setinfo + .DA getinfo + .DA online + .DA setprefx + .DA getprefx + .DA openf + .DA newline + .DA readf + .DA writef + .DA closef + .DA flushf + .DA setmark + .DA getmark + .DA seteof + .DA geteof + .DA setbuf + .DA getbuf + +* corresponding command function bytes + +disptch .HS A0A1A2A3 + .HS 84050607 + .HS 88494A4B + .HS 2C2D4E4F + .HS 50515253 + +dinctbl .HS 0100000200 table to increment directory usage/eof counts +pass .HS 75 +xdosver .HS 00 +compat .HS 00 + .HS C3270D000000 +rootstuf .HS 0F02000400000800 +whichbit .HS 8040201008040201 +ofcbtbl .HS 0C0D1819151617 +inftabl .HS 1E101F2080939421 + .HS 22232418191A1B +deathmsg .HS 20 + .AS -"RESTART SYSTEM-$01" + .HS 20 + +*** work space *** + +* note: this area is accessed by code that depends on the order of these +* variables in the file control block and temporary directory. + +own_blk .HS 0000 +own_ent .HS 00 +own_len .HS 00 +h_credt .HS 0000 directory creation date + .HS 0000 directory creation time + .HS 00 version under which this dir created + .HS 00 earliest version that it's compatible +h_attr .HS 00 attributes (protect bit, etc.) +h_entln .HS 00 length of each entry in this directory +h_maxent .HS 00 maximum number of entries per block +h_fcnt .HS 0000 current # of files in this directory +h_bmap .HS 0000 address of first allocation bitmap +h_tblk .HS 0000 total number of blocks on this unit +d_dev .HS 00 device number of this directory entry +d_head .HS 0000 address of directory header +d_entblk .HS 0000 address of block which contains entry +d_entnum .HS 00 entry number within block +d_stor .HS 0000000000000000 file name + .HS 0000000000000000 +d_filid .HS 00 user's identification byte +d_frst .HS 0000 first block of file +d_usage .HS 0000 # of blocks allocated to this file +d_eof .HS 000000 current end of file marker +d_credt .HS 0000 file creation date + .HS 0000 file creation time +d_sosver .HS 00 sos version that created this file +d_comp .HS 00 backward version compatibility +d_attr .HS 00 attributes (protect, r/w, enable, etc.) +d_auxid .HS 0000 user auxilliary identification +d_moddt .HS 0000 file's last modification date + .HS 0000 file's last modification time +d_dhdr .HS 0000 file directory header block address + +scrtch .HS 00000000 scratch area for allocation address conversion. +oldeof .HS 000000 temp used in r/w +oldmark .HS 000000 +xvcbptr .HS 00 used in 'cmpvcb' as a temp +vcbptr .HS 00 +fcbptr .HS 00 +fcbflg .HS 00 +reql .HS 00 +reqh .HS 00 +levels .HS 00 +totent .HS 00 +entcntl .HS 00 +entcnth .HS 00 +cntent .HS 00 +nofree .HS 00 +bmcnt .HS 00 +saptr .HS 00 +pathcnt .HS 00 +p_dev .HS 00 +p_blok .HS 0000 +bmptr .HS 00 +basval .HS 00 +half .HS 00 + +* bitmap info tables + +bmastat .HS 00 +bmadev .HS 00 +bmadadr .HS 0000 +bmacmap .HS 00 +tposll .HS 00 +tposlh .HS 00 +tposhi .HS 00 +rwreql .HS 00 +rwreqh .HS 00 +nlchar .HS 00 +nlmask .HS 00 +ioaccess .HS 00 has a call been made to disk device handler ? +cmdtemp .HS 00 +bkbitflg .HS 00 used to set or clear backup bit +duplflag .HS 00 +vcbentry .HS 00 + +* xdos temporary variables + +namcnt .HS 00 +rnptr .HS 00 +namptr .HS 00 +vnptr .HS 00 +prfxflg .HS 00 +cferr .HS 00 + +* deallocation temporary variables + +firstbl .HS 00 +firstbh .HS 00 +stortyp .HS 00 +deblock .HS 0000 +dtree .HS 00 +dsap .HS 00 +dseed .HS 0000 +topdest .HS 00 +dtmpx .HS 00 +loklst .EQ * look list of recognized device numbers +dealbufl .HS 0000000000000000 +dealbufh .HS 0000000000000000 +cbytes .HS 0000 + .HS 00 cbytes+2 must = 0 +bufaddrl .HS 00 +bufaddrh .HS 00 +delflag .HS 00 used by 'detree' to know if called from delete (destroy). + +* zero fill to page boundary - 3 ($FEFD). so that cortland flag stays within page boundary. + .LIST ON +XDOS.FREE .EQ $FEFD-* (ProDOS 2.0.3 = $0C) + .LIST OFF + .BS XDOS.FREE + .DA calldisp +cortflag .HS 00 cortland flag. 1 = Cortland system (must stay within page boundary) +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.XDOS.F +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.XRW.txt b/ProDOS.FX/ProDOS.S.XRW.txt new file mode 100644 index 00000000..61ca82cd --- /dev/null +++ b/ProDOS.FX/ProDOS.S.XRW.txt @@ -0,0 +1,882 @@ +NEW + AUTO 3,1 +* disk ii driver. object code = xrw_0 +* $5300-5A00 moved to language card bank 1 at $D000 +*-------------------------------------- +blockio cld $D8 to flag language card bank 1 (main) + jsr rsetphse + lda q7l,x turn off write enable + nop + nop + jsr docheck + bcs L5334 branch if block # is out of range + ldy #$05 +L5310 asl + rol ibtrk + dey + bne L5310 + asl + bcc L531C + ora #$10 adjust for upper 4 bits of track +L531C lsr + lsr + lsr + lsr + pha save sector # across call + jsr regrwts + pla + bcs L5330 if error + inc buf+1 + adc #$02 + jsr regrwts get 2nd half of block + dec buf+1 +L5330 lda ibstat + rts +L5334 lda #MLI.E.IO + sec + rts + +* read/write a track/sector + +regrwts ldy #$01 retry count + sty seekcnt only one recalibrate per call + sta ibsect + lda unitnum get slot # for this operation + and #$70 + sta A2L + +* make sure other drives in other slots are stopped + + jsr chkprev + +* now check if the motor is on, then start it + + jsr chkdrv + php save test results + lda #$E8 + sta montimeh + lda unitnum determine drive 1 or 2. + cmp iobpdn same drive used before ? + sta iobpdn save it for next time. + php keep results of compare. + asl get drive # into carry. + lda motoron,x turn on the drive. + bcc L5362 branch if drive 1 selected. + inx select drive 2. + +L5362 lda drv0en,x + plp was it the same drive ? + beq L5372 yes. + plp indicate drive off by setting z-flag. + ldy #$07 150ms delay before stepping. +L536B jsr mswait + dey + bne L536B + php now zero flag set. +L5372 lda A4L make sure this command needs seeking. + beq L537C branch if status check. + lda ibtrk get destination track + jsr myseek and go to it. + +* now at desired track. was the motor already on ? + +L537C plp was motor on ? + bne L538E if so, don't wait. + +* motor was off, wait for it to speed up + +L537F lda #$01 wait 100us for each count in montime + jsr mswait + lda montimeh + bmi L537F count up to 0000 + +* motor should be up to speed, +* if it looks stopped then the drive is not present + + jsr chkdrv is drive present ? + beq hndlerr branch if no drive + +* now check: if it is not the format disk command, +* locate the correct sector for this operation + +L538E lda A4L get command # + beq L53FD if 0 then status command + lsr set carry = 1 for read, 0 for write. + bcs L5398 must prenibblize for write + jsr prenib16 +L5398 ldy #$40 64 retries + sty retrycnt +L539D ldx A2L get slot #. + jsr rdadr16 read next address field. + bcc L53BE branch if read ok. +L53A4 dec retrycnt one less chance. + bpl L539D branch to retry. + lda #$27 anticipate a bad drive error. + dec seekcnt can only recalibrate once. + bne hndlerr + lda curtrk + pha save track + asl + adc #$10 pretend track is 8 > curtrk + ldy #$40 + sty retrycnt reset retries to 64 max. + bne L53CC always. + +* have now read an address field. make sure this is +* the correct track, sector and volume. + +L53BE ldy track check track + cpy curtrk + beq L53D5 ok + +* recalibrating from this track + + lda curtrk preserve destination track + pha + tya + asl +L53CC jsr settrk + pla + jsr myseek + bcc L539D always taken, go recalibrate + +* drive is on right track, check volume mismatch + +L53D5 lda sect is this the right sector ? + cmp ibsect + bne L53A4 no, try another sector. + lda A4L read or write ? + lsr the carry will tell. + bcc L53F4 branch if write + jsr read16 + bcs L53A4 if bad read +L53E7 lda #$00 + .HS D0 bne branch never taken (skip 1 byte) +hndlerr sec + sta ibstat error # + ldx A2L slot offset + lda motoroff,x turn off + rts +L53F4 jsr write16 write nibbles +statdne bcc L53E7 if no errors. + lda #$2B disk write protected. + bne hndlerr always +L53FD ldx A2L + lda q6h,x test for write protected + lda q7l,x + rol write protect-->carry-->bit 0=1 + lda q6l,x keep in read mode + jmp statdne +myseek asl assume two phase stepper + sta track save destination track * 2 + jsr alloff turn all phases off to be sure. + jsr drvindx get index to previous track + lda iobpdn,x for current drive. + sta curtrk current position. + lda track where to go next. + sta iobpdn,x + jsr seek move head there +alloff ldy #$03 turn off all phases before returning. +L5427 tya (send phase in acc) + jsr clrphase carry clear, phases should be turned off + dey + bpl L5427 + lsr curtrk divide back down + clc + rts + +* fast seek subroutine +* +* on entry: +* x = slot# times $10 +* acc = desired half-track (single phase) +* curtrk = current halftrack +* +* on exit: +* a,y = uncertain +* x = undisturbed +* curtrk & trkn = final halftrack. +* prior = prior halftrack if seek was required. +* montimel,h are incremented by the # of 100us quantums required by +* seek for motor on time overlap. +* +* variables used: curtrk, trkn, countn, prior, A2L, montimel, montimeh + +seek sta trkn save target track. + cmp curtrk on desired track ? + beq setphase yes, energize phase and return + lda #$00 + sta trkcnt half track count. +L5440 lda curtrk save curtrk for delayed turnoff + sta prior + sec + sbc trkn delta-tracks. + beq L5483 branch if curtrk = destination + bcs mvout move out, not in. + eor #$FF calculate tracks to go. + inc curtrk increment current track (in). + bcc L545A always taken. +mvout adc #$FE calculate tracks to go. + dec curtrk decrement current track (out). +L545A cmp trkcnt + bcc L5462 and 'tracks moved' + lda trkcnt +L5462 cmp #$09 + bcs L5468 if trkcnt > 8 then leave y alone (y=8) + tay else set acceleration index in y + sec +L5468 jsr setphase + lda ontable,y for 'ontime' + jsr mswait (100us intervals) + lda prior + clc for phaseoff + jsr clrphase turn off prior phase + lda offtable,y then wait 'offtime' + jsr mswait (100us intervals) + inc trkcnt count of 'tracks moved' + bne L5440 always taken +L5483 jsr mswait settle 25 msec + + clc set for phase off + +setphase lda curtrk get current track +clrphase and #$03 mask for 1 of 4 phases + rol double for phaseon/off index + ora A2L + tax + lda phaseoff,x turn on/off one phase + ldx A2L restore x reg + rts and return + +* 7-bit to 6-bit 'deniblize' table (16-sector format) +* +* valid codes are $96 to $FF only. codes with more than one pair of +* adjacent zeroes or with no adjacent ones (except bit 7) are excluded. +* +* nibles in the ranges of $A0-$A3, $C0-$C7, $E0-$E3 are used for +* other tables since no valid nibles are in these ranges. + +dnibl .HS 0004FFFF080CFF10 aligned to page boundary minus $96 + .HS 1418 +twobit3 .HS 008040C0FFFF used in fast prenib as lookup for 2-bit quantities. + .HS 1C20FFFFFF24282C + .HS 3034FFFF383C4044 + .HS 484CFF5054585C60 + .HS 6468 +twobit2 .HS 00201030 used in fast prenib. +endmrks .HS DEAAEBFF table using 'unused' nibbles ($C4,$C5,$C6,$C7) + .HS FFFFFF6CFF70 + .HS 7478FFFFFF7CFFFF + .HS 8084FF888C909498 + .HS 9CA0 +twobit1 .HS 0008040CFFA4 used in fast prenib. + .HS A8ACFFB0B4B8BCC0 + .HS C4C8FFFFCCD0D4D8 + .HS DCE0FFE4E8ECF0F4 + .HS F8FC + +* 6-bit to 2-bit conversion tables: +* +* dnibl2 abcdef-->0000FE +* dnibl3 abcdef-->0000DC +* dnibl4 abcdef-->0000BA + +* origin = $D200 (page boundary) +* page align the following tables: + +dnibl2 .HS 00 +dnibl3 .HS 00 +dnibl4 .HS 00 + +* 6-bit to 7-bit nibl conversion table +* +* codes with more than one pair of adjacent zeroes +* or with no adjacent ones (except B7) are excluded. + +nibl .HS 960200 + .HS 00970100009A0300 + .HS 009B0002009D0202 + .HS 009E0102009F0302 + .HS 00A6000100A70201 + .HS 00AB010100AC0301 + .HS 00AD000300AE0203 + .HS 00AF010300B20303 + .HS 00B3000002B40200 + .HS 02B5010002B60300 + .HS 02B7000202B90202 + .HS 02BA010202BB0302 + .HS 02BC000102BD0201 + .HS 02BE010102BF0301 + .HS 02CB000302CD0203 + .HS 02CE010302CF0303 + .HS 02D3000001D60200 + .HS 01D7010001D90300 + .HS 01DA000201DB0202 + .HS 01DC010201DD0302 + .HS 01DE000101DF0201 + .HS 01E5010101E60301 + .HS 01E7000301E90203 + .HS 01EA010301EB0303 + .HS 01EC000003ED0200 + .HS 03EE010003EF0300 + .HS 03F2000203F30202 + .HS 03F4010203F50302 + .HS 03F6000103F70201 + .HS 03F9010103FA0301 + .HS 03FB000303FC0203 + .HS 03FD010303FE0303 + .HS 03FF + +* nibl buffer 'nbuf2' must be on a page boundary !!! + +nbuf2 .BS 86 nibl buffer for read/write of low 2-bits of each byte. +ibtrk .HS 00 +ibsect .HS 00 +ibstat .HS 00 +iobpdn .HS 00 +curtrk .HS 00 + .HS 00000000000000 for slots 1 thru 7 + .HS 00000000000000 drives 1 & 2 +retrycnt .HS 00 +seekcnt .HS 00 +trkcnt .EQ * halftracks moved count. +countn .EQ * 'must find' count. +last .HS 00 'odd bit' nibls. +csum .HS 00 used for address header cksum +csstv .HS 00 +sect .HS 00 +track .EQ * +montimel .HS 00 +montimeh .HS 00 also 'volume' +prior .HS 00 +trkn .HS 00 + +* phase on, off time tables +* in 100 usec intervals (seek) + +ontable .HS 013028 + .HS 24201E1D1C1C +offtable .HS 702C + .HS 26221F1E1D1C1C + +* mswait subroutine +* +* delays a specified number of 100 usec intervals for motor timing. +* on entry: acc holds number of 100 usec intervals to delay. +* on exit: acc = 0, x = 0, y = unchanged, carry set. +* montimel, montimeh are incremented once per 100 usec interval +* for motor on timing. + +mswait ldx #$11 delay 86 usec +.1 dex + bne .1 + inc montimel + bne .2 + inc montimeh +.2 sec + sbc #$01 + bne mswait + rts + +* read address field subroutine (16-sector format) +* +* reads volume, track and sector. +* on entry: x = slot# times $10, read mode (q6l,q7l) +* on exit: carry set if error, else if no error: +* acc=$AA, y=0, x=unchanged, carry clear, +* ccstv contains chksum,sector,track & volume read. +* uses temps: count,last,csum & 4 bytes at ccstv +* expects: original 10-sector normal density nibls (4-bit) odd bits then even. +* observe 'no page cross' warnings on some branches !!! + +rdadr16 ldy #$FC + sty countn 'must find' count +L569D iny + bne L56A5 low order of count. + inc countn (2k nibles to find address mark + beq rderr else error) +L56A5 lda q6l,x read nibl + bpl L56A5 *** no page cross *** +L56AA cmp #$D5 address mark 1 ? + bne L569D + nop nibl delay +L56AF lda q6l,x + bpl L56AF *** no page cross *** + cmp #$AA address mark 2 ? + bne L56AA if not, is it address mark 1 ? + ldy #$03 index for 4 byte read +L56BA lda q6l,x + bpl L56BA *** no page cross *** + cmp #$96 address mark 3 ? + bne L56AA if not, is it address mark 1 + sei no interrupts until address is tested. + lda #$00 init checksum +L56C6 sta csum +L56C9 lda q6l,x read 'odd bit' nibl + bpl L56C9 *** no page cross *** + rol align odd bits, '1' into lsb. + sta last save them. +L56D2 lda q6l,x read 'even bit' nibl + bpl L56D2 *** no page cross *** + and last merge odd and even bits. + sta csstv,y store data byte. + eor csum + dey + bpl L56C6 loop on 4 data bytes. + tay if final checksum non-zero, + bne rderr then error. +L56E6 lda q6l,x first bit-slip nibl + bpl L56E6 *** no page cross *** + cmp #$DE + bne rderr + nop delay +L56F0 lda q6l,x second bit-slip nible + bpl L56F0 *** no page cross *** + cmp #$AA + bne rderr + clc normal read ok + rts +rderr sec + rts + +* read subroutine (16-sector format) +* +* reads encoded bytes into nbuf1 and nbuf2. +* first reads nbuf2 high to low, then nbuf1 low to high. +* on entry: x=slot# times $10, read mode (q6l,q7l) +* on exit: carry set if error, else if no error: +* acc=$AA, x=unchanged, y=0, carry clear. +* observe 'no page cross' on some branches !! + +read16 txa get slot # + ora #$8C prepare mods to read routine. + sta rd4+1 warning: the read routine is + sta rd5+1 self modified !! + sta rd6+1 + sta rd7+1 + sta rd8+1 + lda buf modify storage addresses also + ldy buf+1 + sta ref3+1 + sty ref3+2 + sec + sbc #$54 + bcs L571F branch if no borrow + dey +L571F sta ref2+1 + sty ref2+2 + sec + sbc #$57 + bcs L572B branch if no borrow + dey +L572B sta ref1+1 + sty ref1+2 + ldy #$20 32 tries to find +L5733 dey + beq L576D branch if can't find data header marks +L5736 lda q6l,x + bpl L5736 +L573B eor #$D5 1st data mark + bne L5733 + nop delay +L5740 lda q6l,x + bpl L5740 + cmp #$AA 2nd data mark. + bne L573B if not, check for 1st again + nop +L574A lda q6l,x + bpl L574A + cmp #$AD 3rd data mark + bne L573B if not, check for data mark 1 again + ldy #$AA + lda #$00 +L5757 sta pcl use z-page for keeping checksum +rd4 ldx q6l+$60 warning: self modified + bpl rd4 + lda dnibl-$96,x + sta nbuf2-$AA,y save the two-bit groups in nbuf. + eor pcl update checksum. + iny next position in nbuf. + bne L5757 loop for all $56 two-bit groups. + ldy #$AA now read directly into user buffer. + bne rd5 always taken. +L576D sec error + rts +ref1 sta $1000,y warning: self modified +rd5 ldx q6l+$60 warning: self modified + bpl rd5 + eor dnibl-$96,x get actual 6-bit data from dnib table. + ldx nbuf2-$AA,y get associated two-bit pattern + eor dnibl2,x and combine to form whole byte. + iny + bne ref1 loop for $56 bytes. + pha save for now, no time to store... + and #$FC strip low bits. + ldy #$AA prepare for next $56 bytes +rd6 ldx q6l+$60 warning: self modified + bpl rd6 + eor dnibl-$96,x + ldx nbuf2-$AA,y + eor dnibl3,x +ref2 sta $1000,y warning: self modified + iny + bne rd6 loop unil this group of $56 read + +rd7 ldx q6l+$60 warning: self modified + bpl rd7 + and #$FC + ldy #$AC last group is $54 long +L57A5 eor dnibl-$96,x + ldx nbuf2-$AC,y + eor dnibl4,x combine to form full byte +ref3 sta $1000,y warning: self modified + +rd8 ldx q6l+$60 warning: self modified + bpl rd8 + iny + bne L57A5 + and #$FC + eor dnibl-$96,x checksum ok ? + bne L57CC error if not. + ldx A2L test end marks. +L57C2 lda q6l,x + bpl L57C2 + cmp #$DE + clc + beq L57CD branch if good trailer +L57CC sec +L57CD pla place last byte into user buffer + ldy #$55 + sta (buf),y + rts + +* set the slot dependent track location + +settrk jsr drvindx get index to drive # + sta iobpdn,x + rts + +* determine if motor is stopped +* +* if stopped, controller's shift register will not be changing. +* return y = 0 and zero flag set if it is stopped. + +chkdrv ldx A2L +chkdrv0 ldy #$00 init loop counter. +.1 lda q6l,x read the shift register. + jsr ckdrts delay + pha + pla more delay. + cmp q6l,x has shift reg changed ? + bne ckdrts yes, motor is moving. + lda #$28 anticipate error. + dey no, dec retry counter + bne .1 and try 256 times. +ckdrts rts + +drvindx pha preserve acc across call + lda A4L+1 + lsr + lsr + lsr + lsr + cmp #$08 + and #$07 + rol + tax index to table. + pla restore acc + rts + +* write subroutine (16 sector format) +* +* writes data from nbuf1 and buf. first nbuf2, high to low then direct +* from (buf), low to high. assumes 1 usec cycle time. self modified code !! +* +* on entry: x = slotnum times 16 +* +* on exit: carry set if error (write protect violation). +* if no error, acc=uncertain, x=unchanged, y=0, carry clear. + +write16 sec anticipate write protect error + lda q6h,x + lda q7l,x sense write protect flag + bpl L580C + jmp wexit exit if write protected + +* timing is critical. a one micro-second cycle time is assumed. +* number in () is how many micro-seconds per instruction or subroutine + +L580C lda nbuf2 + sta pcl + lda #$FF sync data. + sta q7h,x (5) goto write mode + ora q6l,x (4) + ldy #$04 (2) for five nibls + nop (2) + pha (3) + pla (4) +wsync pha (3) exact timing. + pla (4) exact timing. + jsr wnibl7 (13,9,6) write sync. + dey (2) + bne wsync (3-) must not cross page ! + lda #$D5 (2) 1st data mark + jsr wnibl9 (15,9,6) + lda #$AA (2) 2nd data mark + jsr wnibl9 (15,9,6) + lda #$AD (2) 3rd data mark + jsr wnibl9 (15,9,6) + tya (2) zero checksum + ldy #$56 (2) nbuf2 index + bne L583D (3) branch always + +* total time in this write byte loop must = 32us !!! + +L583A lda nbuf2,y (4) prior 6-bit nibl +L583D eor nbuf2-1,y (5) xor with current + tax (2) index to 7-bit nibl + lda nibl,x (4) must not cross page boundary + ldx A2L (3) restore slot index + sta q6h,x (5) store encoded byte + lda q6l,x (4) handshake + dey (2) + bne L583A (3-) must not cross page boundary + +* end of write byte loop + + lda pcl (3) get prior nibl (from nbuf2) +wrefd1 ldy #$00 (2) warning: load value modified by prenib. +wrefa1 eor $1000,y (4) warning: address modified by prenib. + and #$FC (2) strip low 2 bits + tax (2) index to nibl table + lda nibl,x (4) +wrefd2 ldx #$60 (2) warning: value modified by prenib. + sta q6h,x (5) write nibl + lda q6l,x (4) handshake +wrefa2 lda $1000,y (4) prior nibl. warning: address modified by prenib. + iny (2) all done with this page ? + bne wrefa1 (3-) loop until page end. + lda pch (3) get next (precalculated & translated) nibl. + beq L58C0 (2+) branch if code written was page aligned. + lda A2H (3) get byte address of last byte to be written. + beq L58B3 (2+) branch if only 1 byte left to write. + lsr (2) test for odd or even last byte (carry set/clear) + lda pch (3) restore nibl to acc. + sta q6h,x (5) + lda q6l,x (4) + lda A1L (3) = byte 0 of 2nd page xor'd with byte 1 if + nop (2) above test set carry. + iny (2) y=1 + bcs L5899 (2+) branch if last byte to be odd. +wrefa3 eor $1100,y (4) warning: address modified by prenib. + and #$FC (2) strip low 2 bits. + tax (2) index to nibl table + lda nibl,x (4) get nibl +wrefd3 ldx #$60 (2) restore slot index. warning: modified by prenib + sta q6h,x (5) + lda q6l,x (4) +wrefa4 lda $1100,y (4) warning: modified by prenib + iny (2) got prior nibl, point to next +wrefa5 eor $1100,y (4) warning: modified by prenib +L5899 cpy A2H (3) set carry if this is the last nibl + and #$FC (2) strip low 2 bits + tax (2) + lda nibl,x (4) +wrefd4 ldx #$60 (2) restore slot. warning: modified by prenib + sta q6h,x (5) + lda q6l,x (4) +wrefa6 lda $1100,y (4) get prior nibl. warning: modified by prenib + iny (2) + bcc wrefa3 (3-) branch if not the last. + bcs L58B1 (3) waste 3 cycles, branch always. +L58B1 bcs L58C0 (3) branch always. +L58B3 lda >pch (4) absolute reference to zero page + sta q6h,x (5) + lda q6l,x (4) + pha (3) waste 14 micro-seconds total + pla (4) + pha (3) + pla (4) +L58C0 ldx A1H (3) use last nibl (anded with $FC) for checksum + lda nibl,x (4) +wrefd5 ldx #$60 (2) restore slot. warning: modified by prenib + sta q6h,x (5) + lda q6l,x (4) + ldy #$00 (2) set y = index end mark table. + pha (3) waste another 11 micro-seconds + pla (4) + nop (2) + nop (2) +L58D3 lda endmrks,y (4) dm4, dm5, dm6 and turn off byte. + jsr wnibl (15,6) write it + iny (2) + cpy #$04 (2) have all end marks been written ? + bne L58D3 (3) if not. + clc (2,9) +wexit lda q7l,x out of write mode + lda q6l,x to read mode. + rts return from write. + +* 7-bit nibl write subroutines + +wnibl9 clc (2) 9 cycles, then write. +wnibl7 pha (3) 7 cycles, then write. + pla (4) +wnibl sta q6h,x (5) nibl write + ora q6l,x (4) clobbers acc, not carry + rts (6) + +* preniblize subroutine (16 sector format) +* +* converts 256 bytes of user data in (buf) into 6 bit nibls in nbuf2. +* high 6 bits are translated directly by the write routines. +* +* on entry: buf is 2-byte pointer to 256 bytes of user data. +* +* on exit: a,x,y undefined. write routine modified to do direct conversion +* of high 6 bits of user's buffer data. + +prenib16 lda buf self-modify the addresses because of + ldy buf+1 the fast timing required. + clc all offsets are minus $AA. + adc #$02 the highest set is buf+$AC. + bcc L58FA branch if no carry, + iny otherwise add carry to high address. +L58FA sta prn3+1 self mod 3 + sty prn3+2 + sec + sbc #$56 middle set is buf+$56. + bcs L5906 branch if no borrow, + dey otherwise deduct from high. +L5906 sta prn2+1 self mod 2 + sty prn2+2 + sec + sbc #$56 low set is exactly buf + bcs L5912 + dey +L5912 sta prn1+1 self mod 1 + sty prn1+2 + ldy #$AA count up to 0. +prn1 lda $1000,y warning: self modified. get byte from lowest group. + and #$03 strip high 6 bits. + tax index to 2 bit equivalent. + lda twobit1,x + pha save pattern +prn2 lda $1056,y warning: self modified. get byte from middle group. + and #$03 + tax + pla restore pattern. + ora twobit2,x combine 2nd group with 1st. + pha save new pattern. +prn3 lda $10AC,y warning: self modified. get byte from highest group. + and #$03 + tax + pla restore new pattern + ora twobit3,x and form final nibl. + pha + tya + eor #$FF + tax + pla + sta nbuf2,x save in nibl buffer. + iny inc to next set. + bne prn1 loop until all $56 nibls formed. + ldy buf now prepare data bytes for write16 subr. + dey prepare end address. + sty A2H + lda buf + sta wrefd1+1 warning: the following storage addresses + beq L595F starting with 'wref' are refs into code + eor #$FF space, changed by this routine. + tay index to last byte of page in (buf). + lda (buf),y pre-niblize the last byte of the page + iny with the first byte of the next page. + eor (buf),y + and #$FC + tax + lda nibl,x get disk 7-bit nible equivalent. +L595F sta pch + beq L596F branch if data to be written is page + lda A2H aligned. check if last byte is even + lsr or odd address. shift even/odd -> carry. + lda (buf),y if even, then leave intact. + bcc L596D branch if odd. + iny if even, then pre-xor with byte 1. + eor (buf),y +L596D sta A1L save result for write routine. +L596F ldy #$FF index to last byte of data to write. + lda (buf),y to be used as a checksum. + and #$FC strip extra bits + sta A1H and save it. + ldy buf+1 now modify address references to + sty wrefa1+2 user data. + sty wrefa2+2 + iny + sty wrefa3+2 + sty wrefa4+2 + sty wrefa5+2 + sty wrefa6+2 + ldx A2L and lastly, index references to + stx wrefd2+1 controller. + stx wrefd3+1 + stx wrefd4+1 + stx wrefd5+1 + rts +chkprev eor iobpdn same slot as last ? + asl + beq L59BD + lda #$01 + sta montimeh +L59A6 lda iobpdn + and #$70 + tax + beq L59BD branch if no previous ever (boot only). + jsr chkdrv0 check if previous drive running. + beq L59BD branch if stopped. + lda #$01 delay + jsr mswait + lda montimeh + bne L59A6 +L59BD rts +rsetphse lda unitnum get unit number. + and #$7F mask off high bit. + tax + +* clear all the phases and force read mode + + lda phaseoff+0,x make sure all motor phases are off. + lda phaseoff+2,x + lda phaseoff+4,x + lda phaseoff+6,x + rts +docheck lda A4L command #. + cmp #$04 is the command allowed ? + bcs L59E6 if not. + lda bloknml + ldx bloknml+1 + stx ibtrk calculate block's track and sector. + beq L59E8 branch if block # is in range, + dex else test further. + bne L59E6 taken if bad range. + cmp #$18 must be < $118 + bcc L59E8 then ok. +L59E6 sec error. + rts +L59E8 clc + rts end of obj xrw_0 + .LIST ON +XRW.FREE .EQ $D6EC-* + .LIST OFF + .BS XRW.FREE pad bytes to $D6EC (pathbuf-$14) +* variables used by mli for smartport interface + +spstatlist .HS 00000000 ref pathbuf-$14 smartport status list buffer +spunit .HS 0000000000000000 ref pathbuf-$10smartport unit numbers + .HS 0000000000000000 + +* pathname buffer starts at this page boundary (pathbuf = $D700) +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S.XRW +LOAD USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/ProDOS.FX/ProDOS.S.txt b/ProDOS.FX/ProDOS.S.txt new file mode 100644 index 00000000..ad8ea0d8 --- /dev/null +++ b/ProDOS.FX/ProDOS.S.txt @@ -0,0 +1,228 @@ +NEW + AUTO 3,1 + .LIST OFF + .OP 65816 + .OR $2000 + .TF PRODOS,TSYS +*-------------------------------------- + .INB INC/ZP.I + .INB INC/IO.I + .INB INC/MONITOR.I + .INB INC/MLI.I + .INB INC/MLI.E.I +*-------------------------------------- +MMStartUp .EQ $0202 +NewHandle .EQ $0902 +PtrToHand .EQ $2802 +MessageCenter .EQ $1501 +DisposeHandle .EQ $1002 +MMShutDown .EQ $0302 +ReadTimeHex .EQ $0D03 +Int2Hex .EQ $220B +TLTextMountVolume .EQ $1201 +*-------------------------------------- + .MA SHORTMX + sep #$30 + .EM + .MA SHORTM + sep #$20 + .EM + .MA SHORTX + sep #$10 + .EM + .MA LONGMX + rep #$30 + .EM + .MA LONGM + rep #$20 + .EM + .MA LONGX + rep #$10 + .EM +*-------------------------------------- + .MA IIGS + ldx ##]1 + jsl $E10000 + .EM +*-------------------------------------- +P8QUIT .EQ $E0D000 +GSOS .EQ $E100A8 +GSOS2 .EQ $E100B0 +OS_BOOT .EQ $E100BD indicates O/S initially booted*-------------------------------------- +lookptr .EQ $0A +idapple .EQ $0C model machine id +idxl .EQ $10 general use 16 bit index pointer +devid .EQ $12 +src .EQ $12 +dst .EQ $14 +cnt .EQ $16 +cde .EQ $18 +ecde .EQ $1A + +wndbtm .EQ $23 + + +pcl .EQ $3A +pch .EQ $3B +A1L .EQ $3C +A1H .EQ $3D +A2L .EQ $3E +A2H .EQ $3F +A3L .EQ $40 +A4L .EQ $42 +unitnum .EQ $43 +buf .EQ $44 2-byte data buffer pointer which +accsav .EQ $45 overlaps accsav (temp acc save byte) +bloknml .EQ $46 used mostly as 16 bit block # pointer +zpt .EQ $48 highly used zero page index pointer +datptr .EQ $4A ptr to data area of buffer. +sos .EQ $4C sos buffer pointer. +usrbuf .EQ $4E data ptr in user buffer. + +* zero page variables for Bird's Better Bye + +smparms .EQ $60 set mark parms +sm_refn .EQ $61 file reference number +fpos_lo .EQ $62 new file position (3 bytes) +fpos_mid .EQ $63 +fpos_hi .EQ $64 +lstpntr .EQ $65 device list pointer (16 bit) +valcnt .EQ $67 name counter + +filecount .EQ $68 # of displayable files in directory +namelen .EQ $69 length of filename +gp_cnt .EQ $6A general purpose counter +dlevel .EQ $6B directory level +fnstore .EQ $6C filename storage pointer (16 bit) +entlen .EQ $6E directory entry length +entblk .EQ $6F directory entries/block +filecnt .EQ $70 directory file count (16 bit) +blkfl .EQ $72 block flag / file counter +topname .EQ $73 index # of top name in display +filetyps .EQ $74 128 byte table of filetypes +errnum .EQ $DE +*-------------------------------------- +tst128 .EQ $0080 temp page 0 routine for memory test +auxsp .EQ $0101 +RAMXDRV .EQ $0200 load address for aux bank /RAM driver +inbuf .EQ $0200 keyboard buffer +pbuf .EQ $0280 prefix buffer +p3vect .EQ $03F0 page 3 vectors (16 bytes) +softev .EQ $03F2 RESET vector +pwredup .EQ $03F4 power up byte +nmivect .EQ $03FB nmi handler +txtp2 .EQ $0400 test location for aux card +vmode .EQ $04FB video firmware operating mode +clkmode .EQ $0538 clock mode +ch80col .EQ $057B 80 column ch position +vline5 .EQ $0600 line 5 of display +vline10 .EQ $04A8 line 10 of display +vline11 .EQ $0528 line 11 of display +vline12 .EQ $05A8 line 12 of display +vline13 .EQ $0628 line 13 of display +vline14 .EQ $06A8 line 14 of display +vline16 .EQ $07A8 line 16 of display +vline23 .EQ $0750 line 23 of display +vline24 .EQ $07D0 line 24 of display + +DirBlkBuf .EQ $0C00 +dbuf .EQ $0C00 8 page directory buffer +vblock1 .EQ $0E00 ramdisk directory block +volbuf .EQ $0F00 volume buffer +dispadr .EQ $1000 +iobuf .EQ $1400 i/o buffer +fbuf .EQ $1800 FCB buffer +op_buf .EQ $1C00 open file buffer (selector) +sysentry .EQ $2000 .SYS file load address + +phaseoff .EQ $C080 disk port +motoroff .EQ $C088 disk port +motoron .EQ $C089 disk port +drv0en .EQ $C08A disk port +q6l .EQ $C08C disk port +q6h .EQ $C08D disk port +q7l .EQ $C08E disk port +q7h .EQ $C08F disk port + +rdtcp .EQ $C108 Thunderclock read entry +wttcp .EQ $C10B Thunderclock write entry + +auxmove .EQ $C311 move (3C)-(3E) to (42) +xfer .EQ $C314 + +rwts .EQ $D000 disk ii driver in bank 1 +displc2 .EQ $D100 system death routine stored in bank 2 +pathbuf .EQ $D700 pathname buffer +tclk_in .EQ $D742 clock driver in bank 2 +fcbbuf .EQ $D800 fcb buffer +vcbbuf .EQ $D900 vcb buffer +bmbuf .EQ $DA00 512 byte bitmap buffer +gbuf .EQ $DC00 general purpose 512 byte block buffer +*-------------------------------------- +* $2000 mli_0 mli loader/relocator +* $2C80 ram_1 installer for /RAM +* $2D00 ram_2 /RAM driver in main lc +* $2D9B mli_3 interrupts +* $2E00 mli_1 global page +* $2F00 tclock_0 Thunderclock driver +* $2F80 cclock_0 Cortland clock driver +* $3000 mli_2 xdos mli & block file manager +* $5100 ram_0 /RAM driver in aux mem +* $5300 xrw_0 disk core routines +* $5A00 sel_0 dispatcher +* $5D00 sel_1 enhanced quit code (Bird's Better Bye) +* $6000 sel_2 GQuit dispatcher support +*-------------------------------------- + .INB USR/SRC/PRODOS.FX/PRODOS.S.LDR.A + .INB USR/SRC/PRODOS.FX/PRODOS.S.LDR.B + +RAM .PH $FF00 + .INB USR/SRC/PRODOS.FX/PRODOS.S.RAM + .EP +IRQ .PH $FF9B + .INB USR/SRC/PRODOS.FX/PRODOS.S.IRQ + .EP + +GP .PH $BF00 + .INB USR/SRC/PRODOS.FX/PRODOS.S.GP + .EP + +TCLK .PH $D742 + .INB USR/SRC/PRODOS.FX/PRODOS.S.TCLK + .EP +CCLK .PH $D742 + .INB USR/SRC/PRODOS.FX/PRODOS.S.CCLK + .EP + +XDOS .PH $DE00 + .INB USR/SRC/PRODOS.FX/PRODOS.S.XDOS.A + .INB USR/SRC/PRODOS.FX/PRODOS.S.XDOS.B + .INB USR/SRC/PRODOS.FX/PRODOS.S.XDOS.C + .INB USR/SRC/PRODOS.FX/PRODOS.S.XDOS.D + .INB USR/SRC/PRODOS.FX/PRODOS.S.XDOS.E + .INB USR/SRC/PRODOS.FX/PRODOS.S.XDOS.F + .EP + +RAMX .PH $200 + .INB USR/SRC/PRODOS.FX/PRODOS.S.RAMX + .EP + +XRW .PH $D000 + .INB USR/SRC/PRODOS.FX/PRODOS.S.XRW + .EP + +SEL0 .PH $1000 + .INB USR/SRC/PRODOS.FX/PRODOS.S.SEL0 + .EP + +SEL1 .PH $1000 + .INB USR/SRC/PRODOS.FX/PRODOS.S.SEL1 + .EP + +SEL2 .PH $1000 + .INB USR/SRC/PRODOS.FX/PRODOS.S.SEL2 + .EP +*-------------------------------------- +MAN +SAVE USR/SRC/PRODOS.FX/PRODOS.S +ASM diff --git a/SHARED/X.UNPAK.S.txt b/SHARED/X.UNPAK.S.txt index 33c0e613..9a9d98e2 100644 --- a/SHARED/X.UNPAK.S.txt +++ b/SHARED/X.UNPAK.S.txt @@ -10,18 +10,7 @@ NEW * ZPPtr2 * ZPInMask,ZPBLOfsLBits,ZPBLOfsHBits,ZPBLLenBits *-------------------------------------- -X.Unpak lda (ZPInBufPtr) ULEN LO - eor #$ff - sta ZPnCnt - - jsr X.Unpak.NextByte - - lda (ZPInBufPtr) ULEN HI - eor #$ff - sta ZPnCnt+1 - - jsr X.Unpak.NextByte - +X.Unpak >DEBUG lda (ZPInBufPtr) CHNK.DATA.T bne X.Unpak.PAK *-------------------------------------- @@ -63,6 +52,18 @@ X.Unpak.PAK pha A = BLBITS jsr X.Unpak.NextByte get TOPCNT + lda (ZPInBufPtr) ULEN LO + eor #$ff + sta ZPnCnt + + jsr X.Unpak.NextByte + + lda (ZPInBufPtr) ULEN HI + eor #$ff + sta ZPnCnt+1 + + jsr X.Unpak.NextByte + lda (ZPInBufPtr) CHNK.DATA.PAK.TOPLEN tax jsr X.Unpak.NextByte get TOPCNT