>HADFS5 v5.78 > OSARGS, OSFIND, OSBGET, OSBPUT - File open/close/get/put > ======================================================== ( 01/01/1992, 9:45pm 2 BootOpt moved to H2 <" FindSect sets sect and &C2/3 F Can openin($) P6 v5.30 Accesses context variables in new location Z' v5.51 OSARGS &FD moved to &FD/&FE dJ v5.53 Updating for 24-bit disks, CheckOpen starts at CHNINFO not &90 n= Also need to ensure all OSARGS calls return A correctly x+ v5.63 Channel buffers can be in Hazel / v5.66 Removed code for NotHazel, WS=&1000 I v5.78 fptr stored in channel information, extends zero-length files : 0D=3: Offset to drive number in channel info :  "Assembling S.HADFS5" O%=P%-Block%+mcode% [OPT0 : .args JSR GrabAbs STA argnum:CLC:ADC #3 CMP #10:BCS args_exit /STA ws :\ Save function ,TXA:PHA:TYA:TAX:PLA:TAY :\ Swap X & Y ,PHA:TXA:PHA :\ Save X & Y "9BEQ args2 :\ Y=0, no handle supplied ,?LDA ws:CLC:ADC #10:PHA :\ Add offset to argsY functions 68CMP #12:BCC args1 :\ Not a channel function @:JSR CheckChannelX :\ This corrupts argtmp/buf JJSR clearEOF T .args1 ^:PLA:STA ws :\ Get function offset back h .args2 rSTY ws+1:LDA ws:ASL A:TAY |LDA argsTable,Y:STA ws 'LDA argsTable+1,Y:LDY ws+1:STA ws+1 JLDA argnum:JSR JumpWS :\ Enter with A=function, X=handle, Y=>data STA argnum /PLA:TAY:PLA:TAX :\ Restore X & Y .args_exit LDA argnum:RTS : .argsTable EQUW args0_FD:EQUW args0_FE EQUW args0_FF:EQUW args0_00 EQUW args0_01:EQUW args0_02 EQUW args0_03:EQUW args0_04 EQUW args0_05:EQUW args0_06 \ EQUW argsY_FD:EQUW argsY_FE EQUW argsY_FF:EQUW argsY_00 &EQUW argsY_01:EQUW argsY_02 0EQUW argsY_03:EQUW argsY_04 :EQUW argsY_05:EQUW argsY_06 D: N8\ -------------------------------------------------- X8\ OSARGS &FD,0 - Read version number and information b8\ -------------------------------------------------- l6\ On exit, A=xx from version x.xz, eg 54 for v5.42 vA\ zp=&yzxxaabb from version x.yz and capability aabb ,\ eg &4205aabb for version 5.42 8\ --------------------------------------------------  .args0_FD LDA #able% &FF:STA 0,Y LDA #able% 256:STA 1,Y LDA #("&"+ver$):STA 2,Y "LDA #("&"+ver$,3,2)):STA 3,Y 1LDA # ver$*10+ ver$,1+ver$,"."))/10:RTS : /\ ----------------------------------------- /\ OSARGS &FD/&FE,Y - Read/Write system info /\ ----------------------------------------- +\ OSARGS &FD - Write system information *\ OSARGS &FE - Read system information  %\ Y=25-29 - CSD/LIB/URD/USER/CURR /\ -----------------------------------------  .argsY_FD:.argsY_FE *-\ 25 26 27 28 29 45\ CSD LIB URD /OPT/PRV CURR FLG// >6\ &70 &74 &78 &7C &80 &84 H\ R.PHA:TXA:JSR ChannelRange :\ Check handle \LDA numstore,X:STA 3,Y :\ Copy to returned data DEY:DEX:BNE args0_04lp :TXA:STA 3,Y :\ Clear bottom byte : \ ------------------- "\ OSARGS 6,0 - Unused ,\ ------------------- 6 .args0_06 @RTS J: T\ ------------------------ ^\ OSARGS 4,Y - Read Alloc h\ OSARGS 6,Y - Write Alloc r\ ------------------------ | .argsY_06 7JSR argsY_06a :\ Write file allocation  .argsY_04 LDA WS+&14,X:STA 3,Y LDA WS+&13,X:STA 2,Y LDA WS+&12,X:STA 1,Y :LDA #0:BEQ argsY_05a :\ Write &00 as bottom byte : \ --------------------- \ OSARGS 5,Y - Read \ ---------------------  .argsY_05 3JSR CheckEOF :\ Read on channel :STA 3,Y:STA 2,Y:STA 1,Y :\ Write &00 or &FF to data .argsY_05a  STA 0,Y  .ChkEOFne &/LDA #0:RTS :\ false, EQ=1 0: :#\ ----------------------------- D!\ FSC 1 (OSBYTE &7F) - Read N#\ ----------------------------- X.eof b\TXA:JSR CheckChannelX l/JSR CheckEOF:TAX:RTS :\ Return in X v: %\ ------------------------------- !\ CheckEOF - Compare with %\ -------------------------------  .CheckEOF *LDA WS+&08,X:CMP WS+&0C,X:BCC ChkEOFne *LDA WS+&07,X:CMP WS+&0B,X:BCC ChkEOFne *LDA WS+&06,X:CMP WS+&0A,X:BCC ChkEOFne *LDA WS+&05,X:CMP WS+&09,X:BCC ChkEOFne .LDA #&FF:RTS :\ true, EQ=0 : .cmp_alloc \ lo byte must be zeroed #INX:INX:INX:INX:INX:INX:INX:INX  .cmp_EXT  INX:INX:INX:INX  .cmp_PTR  .LDA WS+&08,X:CMP 3,Y:BCC cmp_xt:BNE cmp_xt *.LDA WS+&07,X:CMP 2,Y:BCC cmp_xt:BNE cmp_xt 4.LDA WS+&06,X:CMP 1,Y:BCC cmp_xt:BNE cmp_xt >LDA WS+&05,X:CMP 0,Y H .cmp_xt RRTS \\ CC= M>, M> f\ CS= M<=, M<= p: z.cmp_PTRhi &LDA 3,Y:CMP WS+&08,X:BNE cmp_PTRlo &LDA 2,Y:CMP WS+&07,X:BNE cmp_PTRlo LDA 1,Y:CMP WS+&06,X .cmp_PTRlo RTS \ EQ= PTRhi=Mhi :  .IncPTR SEC &LDA WS+&05,X:ADC #0:STA ptrstore+0 &LDA WS+&06,X:ADC #0:STA ptrstore+1 &LDA WS+&07,X:ADC #0:STA ptrstore+2 &LDA WS+&08,X:ADC #0:STA ptrstore+3 LDY #ptrstore:BNE argsY_01a : \ -------------------- $\ OSARGS 1,Y - Set .\ -------------------- 8 .argsY_01 BJSR CheckDir2 L.argsY_01a VJSR cmp_PTRhi:BEQ argsY_01b `.JSR argsY_FF :\ Flush buffer to disk j.argsY_01b tLDA #&FF:PHA ~JSR cmp_EXT:DEX:DEX:DEX:DEX /BCS argsY_01d :\ is moving backwards .JSR CheckPTRset :\ Can I move past ? 0PLA:JSR argsY_03a :\ moving past , do = DEX:DEX:DEX:DEX .argsY_01c PHA .argsY_01d LDA 0,Y:STA WS+&05,X LDA 1,Y:STA WS+&06,X LDA 2,Y:STA WS+&07,X LDA 3,Y:STA WS+&08,X PLA .argsY_01e RTS : \ -------------------- (\ OSARGS 3,Y - Set 2\ -------------------- < .argsY_03 FJSR CheckDir2 P.argsY_03a ZJSR CheckOut2 dMLDA #&FF:PHA :\ Prepare to return A=&FF, file not extended n@JSR cmp_PTR:BCC argsY_03b :\ new >= , leave unchanged x:JSR argsY_01a:BMI argsY_03c :\ new < , push lower .argsY_03b @JSR cmp_EXT:DEX:DEX:DEX:DEX :\ Compare new with existing MBCS argsY_03c :\ new < , file shrinking, Alloc unchanged HPLA:JSR argsY_06b :\ new > , ensure Alloc is big enough \ Should pad with zeros GLDA #0:PHA :\ Prepare to return A=0, file extended .argsY_03c !INX:INX:INX:INX:BNE argsY_01d : \ --------- \ Set alloc \ --------- #\ On entry, X=>channel, Y=>data -\ On exit, A=0, X,Y preserved for caller -\ --------------------------------------- .argsY_06a "JSR CheckDir2:JSR CheckOut2 ,.argsY_06b 6PJSR cmpAllocs :\ Compare requested Alloc with current Alloc @[BCS argsY_01e:TYA:PHA :\ Requested Alloc <= Existing Alloc, nothing to be done JKLDA CURR+0:PHA:LDA CURR+1:PHA :\ Save to protect SPOOLing of *CAT, etc TILDA CURR+2:PHA:LDA CURR+3:PHA :\ Can't use loop as need both X and Y ^VLDA fptr+1:PHA:LDA fptr+0:PHA :\ Save file pointer to protect SPOOLing *CAT, etc. heJSR CheckDskChg0 :\ Read FSM, load directory, check disk not changed, X Y preserved r=LDA HDR+&0C:BMI argsY_06c :\ BigDir, up to 4G length |;LDA 3,Y:BNE errCantExtend :\ SmallDir, 16M maximum $LDA 2,Y:CMP #8:BCS errCantExtend : .argsY_06c .z% H TYA:PHA:TXA:PHA :\ Save data pointer and info pointer  LDA WS+&14,X:A WS+&13,X A A WS+&12,X:BNE argsY_06d :\ File not zero length, use it G JSR C8to16K:JSR FindFreeSpace:\ Look for 16K space, AXY corrupted = PLA:PHA:TAX :\ Get channel offset back 6 LDA start+0:STA WS+&01,X :\ Set start sector  LDA start+1:STA WS+&02,X  LDA start+2:STA WS+&03,X  JMP argsY_06h /:]: base$<5.78:z%=P%-z%:P%=P%-z%:O%=O%-z% : .argsY_06d &CLC 0ULDA WS+&01,X:ADC WS+&12,X:STA start+0 :\ start=sector after end of existing file :)LDA WS+&02,X:ADC WS+&13,X:STA start+1 D)LDA WS+&03,X:ADC WS+&14,X:STA start+2 N.z% XP TYA:PHA:TXA:PHA :\ Save data pointer and info pointer b0:]: base$>=5.78:z%=P%-z%:P%=P%-z%:O%=O%-z% lMJSR FindFSMEntry:BEQ argsY_06e :\ Returns X=>FSM entry, Y=BigDisk v.errCantExtend >LDA #119:JSR OSBYTE :\ Close Spool/Exec /JSR errors:EQUB 191:EQUS "Can't extend":BRK : .argsY_06e CJSR C8to16K :\ Prepare to ask for 16K D\LDA #0:\STA len+2:\LDA #&40:\STA len+1:\ Prepare to ask for 16K 8TYA:BPL argsY_06f :\ 16-bit FSM EINX:LDA &F24,X:BNE argsY_06g :\ >16M available, use 16K .argsY_06f ELDA &F23,X:BNE argsY_06g :\ >64K available, use 16K ELDA &F22,X:CMP #&40:BCS argsY_06g :\ >16K available, use 16K KSTA len+1 :\ Less than 16K, use it instead .argsY_06g BJSR FindFreeSub :\ Claim space from FSM .argsY_06h >JSR SaveFSM :\ Save updated FSM TPLA:TAX:PLA:TAY:CLC :\ Get info pointer and data pointer back *DLDA WS+&12,X:ADC len+1:STA WS+&12,X :\ Update channel's Alloc 4'LDA WS+&13,X:ADC len+2:STA WS+&13,X >$LDA WS+&14,X:ADC #0:STA WS+&14,X H[CLC:JSR UpdateFromAlloc :\ Look for my directory entry and update length RRJSR cmpAllocs:BCS P%+5:JMP argsY_06c :\ 16K wasn't enough, claim another 16K \: fQPLA:STA fptr+0:PLA:STA fptr+1:LDY #3 :\ Restore fptr for SPOOLed *CAT, etc. p.argsY_06lp2 z:PLA:STA sect,Y:DEY:BPL argsY_06lp2 :\ Restore CURR ;A sect+1:A sect+2 :\ Was CURR valid? aBEQ P%+5:JSR GetDir :\ Refetch if valid so SPOOLed *CAT, etc, can continue buffer T"LDA WS+&00,X: #&20:BNE errEOF ^.JSR CheckEOF:BEQ bget2 :\ Not at h0LDA #&20:JSR set_flag :\ Set flag r1LDA #254:SEC:BCS putget_end :\ Return Cy=1 | .bget2 >JSR InputUpdate :\ Read from disk if needed :LDA WS+&05,X:TAY:LDA (buf),Y :\ Get byte from buffer 1PHA:JSR IncPTR:PLA:CLC :\ Increment 9BCC putget_end :\ Return Cy=0, A=byte :  .bput1 ;LDA buf:PHA:TYA:JSR CheckOutput:\ X=info, (buf)=>buffer 7LDA WS+&05,X:PHA :\ Get buffer offset >BNE P%+5:JSR IncPTR :\ Flush buffer if offset=0 ;PLA:STA WS+&05,X :\ Restore buffer offset >JSR InputUpdate :\ Read from disk if needed ;LDA WS+&05,X:TAY:PLA:STA (buf),Y:\ Store byte in buffer 5PHA:LDA #2:JSR set_flag :\ Buffer modified 1JSR IncPTR:JSR clearEOF:PLA:CLC:\ Increment : .putget_end &/STA buf:PLA:TAY:LDX #3 :\ Restore Y 0.putget_lp2 :EPLA:STA addr,X:DEX:BPL putget_lp2 :\ Restore addr, preserving Cy D;PLA:STA shadow:PLA:TAX:LDA buf:RTS :\ Restore shadow, X N: X.InputUpdate b&\LDA WS+&00,X:\ #1:\BNE InputUpOk lRLDA WS+&00,X: #&41 :\ Test if b6=open for input and b1=buffer loaded vTCMP #&40:BNE InputUpOk :\ If not (open for input and buffer empty), skip [LDA #0:JSR AccessBuffer:LDA #1 :\ Open for input, and buffer empty, need to load buffer  .set_flag 8A WS+&00,X:STA WS+&00,X :\ Update channel flag .InputUpOk RTS : .zero_flag LDA #0:BEQ clr_flag2  .clearEOF  LDA #&DF .clear_flag  WS+&00,X .clr_flag2 STA WS+&00,X  .CheckIsOk RTS  : *.CheckDir:JSR CheckChannel 4.CheckDir2 >%LDA WS+&00,X: #&10:BEQ CheckIsOk H .ChIsADir R!JSR zero_flag:\ Close channel \1JSR errors:EQUB 181:EQUS "Is a directory":BRK f: p.CheckInput zJSR CheckDir LDA WS+&00,X: #&7F:CMP #64 "BCC NOFRead: #4:BNE CheckIsOk  .NOFRead 7JSR errors:EQUB 189:EQUS "Not open for reading":BRK : .CheckOutput JSR CheckDir:.CheckOut2 !LDA WS+&00,X:BPL errNotUpdate .CheckWrite  #8:BNE CheckIsOk .errNotUpdate 6JSR errors:EQUB 193:EQUS "Not open for update":BRK : .CheckPTRset LDA WS+&00,X:BMI CheckWrite /JSR errors:EQUB 183:EQUS "Outside file":BRK $: ..UpdateLength 8SEC B'\.UpdateWithAlloc:\ Enter with CC L&.UpdateFromAlloc:\ Enter with CC VTXA:PHA:TYA:PHA:PHP `\\LDA WS+&01+D,X:\STA drive j.z% tH JSR CheckDskChg0 :\ Check disk, load FSM, get directory ~0:]: base$>=5.78:z%=P%-z%:P%=P%-z%:O%=O%-z% -\ Alloc -> disk has already been checked -\ Length -> disk has already been checked LDA WS+&03,X:STA start+2 LDA WS+&02,X:STA start+1 LDA WS+&01,X:STA start+0 .z% : JSR LookForEntry :\ fptr=>directory entry 0:]: base$>=5.78:z%=P%-z%:P%=P%-z%:O%=O%-z% .z% 5 LDA WS+&16,X:STA fptr+1 :\ fptr=>file entry  LDA WS+&15,X:STA fptr+0 B JSR CreatePutSector :\ Set start sector in file info /:]: base$<5.78:z%=P%-z%:P%=P%-z%:O%=O%-z%  LDY #&12:LDA WS+&09,X 5PLP:BCS UpdateLengthLow :\ CS=make length= KTXA:ADC #8:TAX:LDA #0 :\ CC=make length=Alloc, low byte is zero (.UpdateLengthLow 2+STA (fptr),Y:INY :\ byte 0 <+LDA WS+&0A,X:STA (fptr),Y:INY :\ byte 1 FLDA HDR+&0C:BPL UpdateLen1 P+INY:LDA WS+&0C,X:STA (fptr),Y :\ byte 3 ZDEY:LDA #0:BEQ UpdateLen2 d.UpdateLen1 nLDA (fptr),Y: #&F8 x.UpdateLen2 *A WS+&0B,X:STA (fptr),Y :\ byte 2 JSR SaveThisDir PLA:TAY:PLA:TAX  .UpdateOk RTS : .CheckDskChg0 JSR FindDriveNumber &TXA:PHA:JSR CheckHADFSDisk:PLA:TAX .CheckDskChg \ drive already set LDA WS+&0D,X:STA sect+0 LDA WS+&0E,X:STA sect+1 LDA WS+&0F,X:STA sect+2 JSR GetDir ,LDA WS+&10,X:CMP HDR+&10:BNE DiskChanged ")LDA WS+&11,X:CMP HDR+&11:BEQ UpdateOk ,.DiskChanged 6\JSR ClearDIR:\STA VFLG @LDA #0:STA VFLG J1JSR errorDIR:EQUB 200:EQUS "Disk changed":BRK T: ^ .FindZero hLDA #0:RTS r .find |#JSR GrabAbs:STX blk+0:STY blk+1 CMP #0:BEQ close "CMP #&40:BCC FindZero:JMP open :  .close TYA:BNE CloseOne \ Close all ;LDA #119:JSR OSBYTE:\ Ask MOS to close SPOOL/EXEC files  LDY #25 .CloseAllLp \TYA:JSR ChannelAddrY BEQ Closed JSR CloseChn:.Closed INY:CPY #30:BNE CloseAllLp LDY #0:BEQ Closed_Ok  .CloseOne JSR CheckChannel & .CloseChn 0HSEC:JSR argsY_FFa:BPL CloseInput:\ Update buffer, flagged as closing :: D TYA:PHA N.z% X. JSR CheckDskChg0 :\ check disk, load FSM b/:]: base$<5.78:z%=P%-z%:P%=P%-z%:O%=O%-z% lLJSR UpdateLength :\ load directory, update file length, save directory v/LDA WS+&09,X:PHA :\ save bottom byte of 2CMP #1 :\ C=1, extra sector needed )LDA WS+&01,X:ADC WS+&0A,X:STA start+0 )LDA WS+&02,X:ADC WS+&0B,X:STA start+1 )LDA WS+&03,X:ADC WS+&0C,X:STA start+2 PLA: #255:CMP #255 'LDA WS+&12,X:SBC WS+&0A,X:STA len+1 'LDA WS+&13,X:SBC WS+&0B,X:STA len+2 ]LDA WS+&14,X:SBC WS+&0C,X:BEQ P%+5:JMP errTooLong:\ Can't return len>16M to FSM in one go  \TYA:\PHA  TXA:PHA JSR AddToFSM:JSR SaveFSM PLA:TAX:PLA:TAY : .CloseInput  JSR zero_flag:CPY &256 BNE CloseNotExec  !STA &256:BEQ Closed_Ok:\ EXEC *.CloseNotExec 4CPY &257:BNE Closed_Ok >STA &257:\ SPOOL H.Closed_Ok RLDX blk+0:RTS:\ A=0, Y=chn \: f .open pSTA buf+0:JSR XYtoF2 z#JSR SearchPathBad:JSR CheckPath "JSR CheckDirInfo:\ A=0/1/2/&82  #&7F:\ Root is just a dir. .OpenInX:\ -EXEC : \ Find a channel \ -------------- "\ Search for an unused channel 2\ On exit, Y=channel, X=>channel, A=corrupted 2\ -------------------------------------------- @PHA:LDY #25 :\ Start with channel 25 .FindChanLp :LDX ChnInfo-25,Y :\ X=>channel info ?LDA WS,X:BEQ FindChkChn1 :\ Channel already open .FindChanNxt INY:CPY #30:BCC FindChanLp 0JSR errors:EQUB 192:EQUS "Too many open":BRK $.FindChkChn1 ..z% 8=5.79:z%=P%-z%:P%=P%-z%:O%=O%-z% L.z% V;BIT WHATOS:BMI FindChanOk :\ MI=Master, PL=BBC `/:]: base$<5.79:z%=P%-z%:P%=P%-z%:O%=O%-z% j>LDA OPTFLG: #&40 :\ Check if &10xx usable t7CPX #CHN26 255:BCC FindChanOk :\ Chn>26, use it ~>BEQ FindChkChn2 :\ Chn26, check OPTFLG DLDA buf+0: #&80: #&80 :\ Chn25, can only use for input .FindChkChn2 Q #&FF:BEQ FindChanNxt :\ Chn25 or Chn26 unusable, try another one .FindChanOk : STY argchn:PLA BNE open_file_found "BIT buf+0:BVC open_create_file \ IN or UP LDA buf+0: #8:BEQ OpenExit JMP errNotFound  .OpenExit LDX blk+0:LDY blk+1:RTS  .open_create_file \ OUT & no file, A=0 JSR C8to16K (\STA len+0:\STA len+2 2\LDA #&40:\STA len+1 < TXA:PHA F2LDA #&FF:CLC:JSR CreateEntry:\ Create 16K file P PLA:TAX Z"LDA #&C:STA WS+&00,X:\ WR bits dBNE open_acc_ok n.open_file_found xCMP #2:BNE OpenNotDir BIT buf+0:BMI IsADirError  \ IN(dir) !LDA buf+0: #4:BEQ OpenNotDir .IsADirError JMP errNotFile .OpenNotDir STXA:PHA :\ OpenIn multiple times, OpenOut once only GLDA buf+0:LSR A:A #&80: #&C0 :\ Work out open flag to check for GJSR CheckNotOpen :\ Check if I can open this way 8JSR YDoIOwn:INY:INY:PLA:TAX :\ Y->my 'E' bit  LDA (fptr),Y:ROL A:ROL attrs $DEY:LDA (fptr),Y:ROL A:ROL attrs $DEY:LDA (fptr),Y:ROL A:ROL attrs +LDA attrs: #3: #3:PHA :\ A=000000WR : $LDY #8:LDA (fptr),Y:BPL open_noD ".PLA:A #5:PHA :\ A=00000DWR , .open_noD 6 PLA:ASL A:ASL A:STA WS+&00,X @&LDA buf+0:CMP #&C0:BCS open_acc_ok JLSR A:LSR A:LSR A:LSR A T WS+&00,X: #&0C ^BNE open_acc_ok h STA WS+&00,X:JMP errNoAccess r: |\ Set up channel buffer \ --------------------- .open_acc_ok :  LDY #2  .openlp1 .LDA CURR,Y :STA WS+&0D+2,X :\ Directory ,LDA HDR+&10,Y:STA WS+&10+2,X :\ Disk ID 4LDA fptr,Y :STA WS+&15+2,X :\ Directory entry 1DEX:DEY:BPL openlp1 :\ X is now X-3 : LDY #&12:\ Y=>length JLDA (fptr),Y:STA WS+&09+3,X:CMP #1:INY :\ CS=round alloc up YLDA (fptr),Y:STA WS+&0A+3,X:ADC #0:STA WS+&12+3,X :\ =length, Alloc=(length+255)256 INY:LDA HDR+&0C:PHP "LDA (fptr),Y:PLP:BMI P%+4: #7 ,STA WS+&0B+3,X:ADC #0:STA WS+&13+3,X:INY &,LDA HDR+&0C: #&80:BPL P%+4:LDA (fptr),Y 0(STA WS+&0C+3,X:ADC #0:STA WS+&14+3,X :: DCINY:LDA (fptr),Y:STA WS+&01+3,X :\ Set start sector N'INY:LDA (fptr),Y:STA WS+&02+3,X:INY X,LDA HDR+&0C: #&80:BPL P%+4:LDA (fptr),Y b+STA WS+&03+3,X:LDA drive:STA WS+&04+3,X l: v \LDY #2  \.openlp1 <\LDA CURR,Y:\STA WS+&0F,X :\ Directory ?\DEX:\DEY:\BPL openlp1 :\ X is now X-3 :\LDA HDR+&10:\STA WS+&10+3,X :\ Disk ID  \LDA HDR+&11:\STA WS+&11+3,X : "LDA buf+0: #&C0:A WS+&00+3,X GSTA WS+&00+3,X:ASL A:ASL A :\ Set OUT/IN, Cy=not OUT ILDA #0:LDY #8:BCC P%+4:LDY #4 :\ OUT, =0/=0; IN/UP, =0  .openlp2 9STA WS+&05+3,X:INX:DEY:BNE openlp2 :\ =0, =0 LDA argchn:JMP OpenExit : .ChannelRange  CMP #25:BCC ChnRangeOk  #&FF:CMP #&E2: #&FF  .ChnRangeOk *5RTS:\ Returns CS=25..29, CC=outside channel range 4: >$\ Offsets to channel information H .ChnInfo REQUB CHN25 255 \EQUB CHN26 255 f"EQUB CHN26-(CHN25-CHN26) 255 p$EQUB CHN26-2*(CHN25-CHN26) 255 zEQUB CHNINFO 255 : "\ Addresses of channel buffers 0EQUB &0F:EQUB &10:EQUB &14:EQUB &15:EQUB &16 : .ChannelAddrY TYA .ChannelAddr \ On entry, A=channel ;\ On exit, WS,X=channel info, (buf),Y points to buffer #JSR ChannelRange:BCC errChannel .z% =TAX:JSR WhatMOS :\ CC=Master, CS=BBC ILDA ChnInfo+5-25,X :\ A=high byte of channel buffer ?BCS P%+4:ADC #&B1:STA buf+1 :\ buf=>channel buffer 0:]: base$>=5.79:z%=P%-z%:P%=P%-z%:O%=O%-z% .z% $=TAX:LDA ChnInfo+5-25,X:BIT WHATOS :\ MI=Master, PL=BBC .?BPL P%+4:ADC #&B0:STA buf+1 :\ buf=>channel buffer 8/:]: base$<5.79:z%=P%-z%:P%=P%-z%:O%=O%-z% B>LDA ChnInfo+0-25,X:TAX :\ WS,X=>channel info LLDA #0:STA buf+0 V&7BFF:"Writing over screen.": O%>L%:L%=O% / O%>M%:"Overwriting screen output":7:#0 >"S.HADFS6"