1 ; -*- coding: utf-8 -*-
2 ; DTCforthMSP430FRxxxxSD_LOAD.asm
4 ; Tested with MSP-EXP430FR5969 launchpad
5 ; Copyright (C) <2017> <J.M. THOORENS>
7 ; This program is free software: you can redistribute it and/or modify
8 ; it under the terms of the GNU General Public License as published by
9 ; the Free Software Foundation, either version 3 of the License, or
10 ; (at your option) any later version.
12 ; This program is distributed in the hope that it will be useful,
13 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ; GNU General Public License for more details.
17 ; You should have received a copy of the GNU General Public License
18 ; along with this program. If not, see <http://www.gnu.org/licenses/>.
21 FORTHWORD "{SD_LOAD}" ; SD_LOAD words mark
24 ;-----------------------------------------------------------------------
25 ; SD card OPEN, LOAD subroutines
26 ;-----------------------------------------------------------------------
28 ;Z S">HERE addr u -- HERE move in-line string to a counted string at HERE
29 SQUOTE2HERE MOV @PSP+,X ; X = src
30 MOV &DDP,Y ; Y = dst = HERE
31 MOV.B TOS,W ; W = count
33 MOV.B W,0(Y) ; count at HERE
38 ; rules for registers use
40 ; T = CurrentHdl, pathname
41 ; W = SectorL, (RTC) TIME
42 ; X = SectorH, (RTC) DATE
43 ; Y = BufferPtr, (DIR) EntryOfst, FAToffset
46 ; ----------------------------------;
47 HDLCurClusToFAT1sectWofstY ;WXY Input: HDL_CurCluster, Output: W=FATsector, Y=FAToffset, Cluster=HDL_CurCluster
48 ; ----------------------------------;
49 MOV HDLL_CurClust(T),&ClusterL ;
50 MOV HDLH_CurClust(T),&ClusterH ;
51 ; ----------------------------------;
52 ClusterToFAT1sectWofstY ;WXY Input : Cluster ; Output: W = FATsector, Y = FAToffset
53 ; ----------------------------------;
54 MOV.B &ClusterL+1,W ;3 W = ClusterLoHI
55 MOV.B &ClusterL,Y ;3 Y = ClusterLoLo
56 CMP #2,&FATtype ;3 FAT32?
58 ; JZ ClusterToFAT32sector ;2 yes
59 ; ADD Y,Y ;1 Y = ClusterLoLo << 1
62 ; input : Cluster n, max = 7FFFFF ==> SDcard up to 256 GB
63 ; ClusterLoLo*4 = displacement in 512 bytes sector ==> FAToffset
64 ; ClusterHiLo&ClusterLoHi +C << 1 = relative FATsector + orgFAT1 ==> FATsector
65 ; ----------------------------------;
66 ClusterToFAT32sector ; Input : Cluster ; Output: W=FATsector, Y=FAToffset
67 ; ----------------------------------;
68 MOV.B &ClusterH,X ; X = 0:ClusterHiLo
69 SWPB X ; X = ClusterHiLo:0
70 ADD X,W ; W = ClusterHiLo:ClusterLoHi
71 ; ----------------------------------;
72 SWPB Y ; Y = ClusterLoLo:0
73 ADD Y,Y ;1 Y = ClusterLoLo:0 << 1 + carry for FATsector
74 ADDC W,W ; W = ClusterHiLo:ClusterLoHi << 1 = ClusterHiLo:ClusterL / 128
77 ADD Y,Y ; Y = 0:ClusterLoLo << 1
79 ; ----------------------------------;
83 ; ----------------------------------; Input : Cluster
84 ComputeClusFrstSect ; If Cluster = 1 ==> RootDirectory ==> SectorL = OrgRootDir
85 ; ----------------------------------; Output: SectorL of Cluster
87 MOV &OrgRootDir,&SectorL ;
88 CMP.B #0,&ClusterH ; clusterH <> 0 ?
89 JNE CCFS_AllOthers ; yes
90 CMP #1,&ClusterL ; clusterHL = 1 ? (FAT16 specificity)
91 JZ CCFS_RET ; yes, sectorL for FAT16 OrgRootDIR is done
93 ; ----------------------------------;
94 .IFDEF MPY ; general case
95 ; ----------------------------------;
96 MOV &ClusterL,&MPY32L ;3
97 MOV &ClusterH,&MPY32H ;3
98 MOV &SecPerClus,&OP2 ;5+3
100 MOV &RES1,&SectorH ;5
101 ADD &OrgClusters,&SectorL ;5 OrgClusters = sector of virtual cluster 0, word size
102 ADDC #0,&SectorH ;3 32~
103 ; ----------------------------------;
104 .ELSEIF ; case of no hardware multiplier
105 ; ----------------------------------; Cluster24<<SecPerClus{1,2,4,8,16,32,64} --> ClusFrstSect
106 .word 0152Ah ;6 PUSHM W,X,Y
107 MOV.B &SecPerClus,W ;3 SecPerClus(5-1) = multiplicator
108 MOV &ClusterL,X ;3 Cluster(16-1) --> MULTIPLICANDlo
109 MOV.B &ClusterH,Y ;3 Cluster(21-17) --> MULTIPLICANDhi
111 JC CCFS_NEXT ;2 case of SecPerClus=1
113 ADD X,X ;1 (RLA) shift one left MULTIPLICANDlo16
114 ADDC Y,Y ;1 (RLC) shift one left MULTIPLICANDhi8
115 RRA W ;1 shift one right multiplicator
116 JNC CCFS_LOOP ;2 C = 0 loop back
117 CCFS_NEXT ; C = 1, it's done
118 ADD &OrgClusters,X ;3 OrgClusters = sector of virtual cluster 0, word size
120 MOV X,&SectorL ;3 low result
121 MOV Y,&SectorH ;3 high result
122 .word 01728h ;6 POPM Y,X,W
123 ; ----------------------------------;34~ + 5~ by loop
125 ; ----------------------------------;
128 ; ----------------------------------;
131 ; ----------------------------------;
132 ComputeHDLcurrentSector ;
133 ; ----------------------------------;
134 MOV HDLL_CurClust(T),&ClusterL;
135 MOV HDLH_CurClust(T),&ClusterH;
136 CALL #ComputeClusFrstSect ;
137 MOV.B HDLB_ClustOfst(T),W ;
141 ; ----------------------------------;
146 ; ----------------------------------; input : X = countdown_of_spaces, Y = name pointer in buffer
147 ParseEntryNameSpaces ;XY
148 ; ----------------------------------; output: Z flag, Y is set after the last space char
151 ; ----------------------------------; input : X = countdown_of_spaces, Y = name pointer in buffer
152 ParseEntryNameSpacesLoop ; here X must be > 0
153 ; ----------------------------------; output: Z flag, Y is set after the last space char
154 CMP.B #32,BUFFER(Y) ; SPACE ?
155 JNZ PENSL_END ; no: RET
158 JNZ ParseEntryNameSpacesLoop;
161 ; ----------------------------------;
164 ; sequentially load in BUFFER bytsPerSec bytes of a file opened as read or as load
165 ; if previous bufferLen had a size < bytsPerSec, closes the file.
166 ; if new bufferLen have a size <= BufferPtr, closes the file.
167 ; reload previous LOADed file if exist.
168 ; HDLL_CurSize leaves the not yet read size
169 ; All used registers must be initialized.
170 ; ==================================;
171 Read_File ; <== SD_ACCEPT, READ
172 ; ==================================;
174 MOV #0,&BufferPtr ; reset BufferPtr (the buffer is already read)
175 CMP #bytsPerSec,&BufferLen ;
176 JNZ CloseHandleT ; because this last and incomplete sector is already read
177 SUB #bytsPerSec,HDLL_CurSize(T) ; HDLL_CurSize is decremented of one sector lenght
178 SUBC #0,HDLH_CurSize(T) ;
179 ADD.B #1,HDLB_ClustOfst(T) ; current cluster offset is incremented
180 CMP.B &SecPerClus,HDLB_ClustOfst(T) ; Cluster Bound reached ?
181 JLO SetBufLenAndLoadCurSector ; no
182 ; ----------------------------------;
183 ;SearchNextCluster ; yes
184 ; ----------------------------------;
185 MOV.B #0,HDLB_ClustOfst(T) ; reset Current_Cluster sectors offset
186 CALL #HDLCurClusToFAT1sectWofstY;WXY Output: W=FATsector, Y=FAToffset, Cluster=HDL_CurCluster
187 CALL #ReadFAT1SectorW ;SWX (< 65536)
188 MOV #0,HDLH_CurClust(T) ;
189 MOV BUFFER(Y),HDLL_CurClust(T) ;
190 CMP #1,&FATtype ; FAT16?
191 JZ SetBufLenAndLoadCurSector ;
192 MOV BUFFER+2(Y),HDLH_CurClust(T);
193 ; ==================================;
194 SetBufLenAndLoadCurSector ;WXY <== previous handle reLOAD
195 ; ==================================;
197 ; ----------------------------------;
198 MOV #bytsPerSec,&BufferLen ; preset BufferLen
199 CMP #0,HDLH_CurSize(T) ; CurSize > 65535 ?
200 JNZ LoadHDLcurrentSector ; yes
201 CMP HDLL_CurSize(T),&BufferPtr ; BufferPtr >= CurSize ? (BufferPtr = 0 or see RestorePreviousLoadedFileContext)
202 JHS CloseHandleT ; yes
203 CMP #bytsPerSec,HDLL_CurSize(T) ; CurSize >= 512 ?
204 JHS LoadHDLcurrentSector ; yes
205 MOV HDLL_CurSize(T),&BufferLen ; no: adjust BufferLen
206 ; ==================================;
207 LoadHDLcurrentSector ; <=== OPEN_WRITE_APPEND
208 ; ==================================;
209 CALL #ComputeHDLcurrentSector ; use no registers
210 ; ==================================;
212 ; ==================================;
214 MOV &SectorH,X ; High
215 JMP ReadSectorWX ; then RET
216 ; ----------------------------------;
219 ; if first open_load token, save DefaultInputStream
220 ; if other open_load token, decrement token, save previous context
223 ; Input : EntryOfst, Cluster = EntryOfst(HDLL_FirstClus())
224 ; init handle(HDLL_DIRsect,HDLW_DIRofst,HDLL_FirstClus,HDLL_CurClust,HDLL_CurSize)
225 ; Output: Cluster = first Cluster of file, X = CurrentHdl
226 ; ----------------------------------; input : Cluster, EntryOfst
227 GetFreeHandle ;STWXY init handle(HDLL_DIRsect,HDLW_DIRofst,HDLL_FirstClus = HDLL_CurClust,HDLL_CurSize)
228 ; ----------------------------------; output : T = new CurrentHdl
229 MOV #8,S ; prepare file already open error
231 MOV #0,X ; X = previous handle, init = 0
232 ; ----------------------------------;
234 ; ----------------------------------;
235 CMP.B #0,HDLB_Token(T) ; free handle ?
236 JZ FreeHandleFound ; yes
238 CMP &ClusterH,HDLH_FirstClus(T);
239 JNE SearchNextHandle ;
240 CMP &ClusterL,HDLL_FirstClus(T);
241 JZ InitHandleRET ; error 8: Already Open abort ===>
243 MOV T,X ; handle is occupied, keep it in X as previous handle
244 ADD #HandleLenght,T ;
246 JNZ SearchHandleLoop ;
247 ; ----------------------------------;
248 ADD S,S ; 16 = no more handle error, abort ===>
251 ; ----------------------------------;
252 FreeHandleFound ; T = new handle, X = previous handle
253 ; ----------------------------------;
254 MOV #0,S ; prepare HappyEnd
256 MOV X,HDLW_PrevHDL(T) ; link to previous handle
257 ; ----------------------------------;
258 CheckCaseOfLoadFileToken ;
259 ; ----------------------------------;
260 CMP.B #0,W ; open_type is LOAD?
261 JGE InitHandle ; W>0, no
262 CMP.B #0,X ; existing previous handle?
264 CMP.B #0,HDLB_Token(X) ; previous token is negative? (open_load type)
266 ADD.B HDLB_Token(X),W ; LOAD token = previous LOAD token -1
267 ; ----------------------------------;
269 ; ----------------------------------;
270 MOV.B W,HDLB_Token(T) ; marks handle as open type
271 MOV.B #0,HDLB_ClustOfst(T) ; clear ClustOfst
272 MOV &SectorL,HDLL_DIRsect(T); init handle DIRsectorL
273 MOV &SectorH,HDLH_DIRsect(T);
275 MOV Y,HDLW_DIRofst(T) ; init handle BUFFER offset of DIR entry
276 MOV BUFFER+26(Y),HDLL_FirstClus(T); init handle firstcluster of file (to identify file)
277 MOV BUFFER+20(Y),HDLH_FirstClus(T)
278 MOV BUFFER+26(Y),HDLL_CurClust(T) ; init handle CurrentCluster
279 MOV BUFFER+20(Y),HDLH_CurClust(T)
280 MOV BUFFER+28(Y),HDLL_CurSize(T); init handle LOW currentSizeL
281 MOV BUFFER+30(Y),HDLH_CurSize(T);
282 MOV #0,&BufferPtr ; reset BufferPtr all type of files
283 CMP.B #2,W ; is a WRITE file handle?
284 JZ ComputeHDLcurrentSector ; = 2, is a WRITE file
285 JGE InitHandleRET ; > 2, is a file to be deleted
286 MOV #0,HDLW_BUFofst(T) ; < 2, is a READ or a LOAD file
287 ; ----------------------------------;
289 ; ----------------------------------;
290 CMP.B #-1,W ; is the first loaded file?
291 JZ FirstLoadFileHandle ; = -1, is the first LOADed file
292 JGE SetBufLenAndLoadCurSector ; > -1, is a READ file
293 ADD &TOIN,HDLW_BUFofst(X) ; < -1, is not the first LOADed file: in previous handle, add interpret offset to Buffer offset
294 JMP SetBufLenAndLoadCurSector ; thus, the return to this previous LOADed file will be on next char after current LOAD" cmd.
295 ; ----------------------------------;
296 FirstLoadFileHandle ;
297 ; ----------------------------------;
301 MOV W,&SAVEtsLEN ;3 save remaining lenght
303 MOV X,&SAVEtsPTR ;3 save new input org address
304 MOV #SD_ACCEPT,&ACCEPT+2 ; redirect ACCEPT to SD_ACCEPT
305 JMP SetBufLenAndLoadCurSector ;
306 ; ----------------------------------;
309 ; If closed token = -1, restore DefaultInputStream
310 ; if closed token < -1, restore previous context
311 ; ==================================;
312 CloseHandleT ; <== CLOSE, Read_File, TERM2SD", OPEN_DEL
313 ; ==================================;
315 MOV #0,&BufferLen ; to inform the user that file is closed
316 CMP #0,T ; no handle?
317 JZ InitHandleRET ; RET
318 ; ----------------------------------;
319 .IFDEF SD_CARD_READ_WRITE
320 CMP.B #2,HDLB_Token(T) ; updated file ?
321 JNZ CloseHandleHere ; no
322 CALL #WriteBuffer ;SWXY
323 CALL #OPWW_UpdateDirectory ;SWXY
325 ; ----------------------------------;
327 ; ----------------------------------;
328 MOV.B HDLB_Token(T),W ; to test W=token below
329 MOV.B #0,HDLB_Token(T) ; close handle
330 ; ----------------------------------;
331 MOV @T,T ; T = previous handle
332 MOV T,&CurrentHdl ; becomes current handle
333 ; ----------------------------------;
334 CheckCaseOfClosedLoadedFile ;
335 ; ----------------------------------;
337 JZ CloseFirstLoadedFile ; W=0, this closed LOADed file had not a paren
338 JGE InitHandleRET ; W>0, for READ, WRITE, DEL files
339 ; ----------------------------------;
340 RestorePreviousLoadedFileContext ; W<0, this closed LOADed file had a paren
341 ; ----------------------------------;
342 MOV HDLW_BUFofst(T),&BufferPtr ; restore BufferPtr saved by SD_ACCEPT before interpreting LOAD cmd line
343 JMP SetBufLenAndLoadCurSector ;
344 ; ----------------------------------;
345 CloseFirstLoadedFile ;
346 ; ----------------------------------;
347 MOV &SAVEtsLEN,TOS ; restore lenght
348 MOV &SAVEtsPTR,2(PSP) ; restore pointer for interpret
349 MOV #PARENACCEPT,&ACCEPT+2 ; restore (ACCEPT)
351 ; ----------------------------------;
354 .IFDEF SD_CARD_READ_WRITE
356 ;-----------------------------------------------------------------------
357 ; SD_READ_WRITE FORTH words
358 ;-----------------------------------------------------------------------
361 ; parse string until " is encountered, convert counted string in StringZ
362 ; then parse stringZ until char '0'.
363 ; media identifiers "A:", "B:" ... are ignored (only one SD_Card),
364 ; char "\" as first one initializes rootDir as SearchDir.
365 ; if file found, if not already open and if free handle...
366 ; ...open the file as read and return the handle in CurrentHdl.
367 ; then load first sector in buffer, bufferLen and bufferPtr are ready for read
368 ; currentHdl keep handle that is flagged as "read".
370 ; to read sequentially next sectors use READ word. A flag is returned : true if file is closed.
371 ; the last sector so is in buffer.
373 ; if pathname is a directory, change current directory.
374 ; if an error is encountered, no handle is set, error message is displayed.
376 ; READ" acts also as CD dos command :
377 ; - READ" a:\misc\" set a:\misc as current directory
378 ; - READ" a:\" reset current directory to root
379 ; - READ" ..\" change to parent directory
381 ; to close all files type : WARM (or COLD, RESET)
383 ; ----------------------------------;
384 FORTHWORDIMM "READ\34" ; immediate
385 ; ----------------------------------;
387 MOV.B #1,W ; W = OpenType
389 ; ----------------------------------;
391 ;Z WRITE" pathame" -- immediate
392 ; open or create the file designed by pathname.
393 ; an error occurs if the file is already opened.
394 ; the last sector of the file is loaded in buffer, and bufferPtr leave the address of the first free byte.
395 ; compile state : compile WRITE" pathname"
396 ; exec state : open or create entry selected by pathname
397 ; ----------------------------------;
398 FORTHWORDIMM "WRITE\34" ; immediate
399 ; ----------------------------------;
401 MOV.B #2,W ; W = OpenType
403 ; ----------------------------------;
406 ;Z DEL" pathame" -- immediate
407 ; compile state : compile DEL" pathname"
408 ; exec state : DELETE entry selected by pathname
410 ; ----------------------------------;
411 FORTHWORDIMM "DEL\34" ; immediate
412 ; ----------------------------------;
414 MOV.B #4,W ; W = OpenType
416 ; ----------------------------------;
419 .ENDIF ; SD_CARD_READ_WRITE
421 ;-----------------------------------------------------------------------
422 ; SD_CARD_LOADER FORTH word
423 ;-----------------------------------------------------------------------
426 ; close current handle
427 ; ----------------------------------;
429 ; ----------------------------------;
432 ; ----------------------------------;
434 ;Z LOAD" pathame" -- immediate
435 ; compile state : compile LOAD" pathname"
436 ; exec state : open a file from SD card via its pathname
437 ; see Open_File primitive for pathname conventions
438 ; the opened file becomes the new input stream for INTERPRET
439 ; this command is recursive, limited only by the count of free handles (up to 8)
441 ; LOAD" acts also as dos command "CD" :
442 ; - LOAD" \misc\" set a:\misc as current directory
443 ; - LOAD" \" reset current directory to root
444 ; - LOAD" ..\" change to parent directory
446 ; ----------------------------------;
447 FORTHWORDIMM "LOAD\34" ; immediate
448 ; ----------------------------------;
449 MOV.B #-1,W ; W = OpenType
450 ; ----------------------------------;
453 ; ======================================================================
454 ; OPEN FILE primitive
455 ; ======================================================================
457 ; primitive for LOAD" READ" CREATE" WRITE" DEL"
458 ; store OpenType on TOS,
459 ; compile state : compile OpenType, compile SQUOTE and the string of provided pathname
460 ; exec state : open a file from SD card via its pathname
461 ; convert counted string found at HERE in a StringZ then parse it
462 ; media identifiers "A:", "B:" ... are ignored (only one SD_Card),
463 ; char "\" as first one initializes rootDir as SearchDir.
464 ; if file found, if not already open and if free handle...
465 ; ...open the file as read and return the handle in CurrentHdl.
466 ; if the pathname is a directory, change current directory, no handle is set.
467 ; if an error is encountered, no handle is set, an error message is displayed.
469 ; ----------------------------------;
471 ; ----------------------------------;
474 MOV W,TOS ; -- Open_type (0=LOAD", 1=READ", 2=WRITE", 4=DEL")
478 mDOCOL ; if compile state
479 .word lit,lit,COMMA,COMMA ; compile open_type as literal
483 .word SQUOTE ; compile string_exec + string
484 .word lit,SQUOTE2HERE,COMMA ; compile move in-line string to a counted string at HERE
485 .word lit,ParenOpen,COMMA ; compile (OPEN)
489 mDOCOL ; if exec state
490 .word lit,34,WORDD ; -- open_type HERE
493 ; ----------------------------------;
494 ParenOpen ; open_type HERE --
495 ; ----------------------------------;
496 ; SUB #2,PSP ; make room for DIRsector
497 ; ----------------------------------;
498 OPN_CountedToStringZ ;
499 ; ----------------------------------;
500 MOV.B @TOS+,Y ; Y=count, TOS = HERE+1
501 ADD TOS,Y ; Y = end of counted string
502 MOV.B #0,0(Y) ; open_type address_of_stringZ --
503 ; ----------------------------------;
505 ; ----------------------------------;
507 MOV &DIRClusterL,&ClusterL ;
508 MOV &DIRclusterH,&ClusterH ;
509 CMP.B #0,0(TOS) ; first char = 0 ?
510 JZ OPN_NoPathName ; error 1 ===>
511 CMP.B #':',1(TOS) ; A: B: C: ... in pathname ?
512 JNZ OPN_AntiSlashStartTest ; no
513 ADD #2,TOS ; yes : skip drive because not used, only one SD_card
514 OPN_AntiSlashStartTest ;
515 CMP.B #5Ch,0(TOS) ; "\" as first char ?
516 JNZ OPN_SearchDirSector ; no
517 ADD #1,TOS ; yes : skip '\' char
518 MOV &FATtype,&ClusterL ; FATtype = 1 as FAT16 RootDIR, FATtype = 2 = FAT32RootDIR
520 ; ----------------------------------;
521 OPN_EndOfDIRstringZtest ; <=== dir found in path
522 ; ----------------------------------;
523 CMP.B #0,0(TOS) ; End of pathname ?
524 JZ OPN_SetCurrentDIR ; yes
525 ; ----------------------------------;
526 OPN_SearchDirSector ;
527 ; ----------------------------------;
528 MOV TOS,&Pathname ; save name addr
529 CALL #ComputeClusFrstSect ; output: SectorHL
530 ; MOV #32,0(PSP) ; preset countdown for FAT16 RootDIR sectors
531 MOV #32,rDODOES ; preset countdown for FAT16 RootDIR sectors
532 CMP #2,&FATtype ; FAT32?
533 JZ OPN_SetDirSectors ; yes
534 CMP &ClusterL,&FATtype ; FAT16 AND RootDIR ?
535 JZ OPN_LoadSectorDir ; yes
537 ; MOV &SecPerClus,0(PSP) ;
538 MOV &SecPerClus,rDODOES ;
539 ; ----------------------------------;
540 OPN_LoadSectorDir ; <=== Dir Sector loopback
541 ; ----------------------------------;
542 CALL #ReadSector ;SWX
543 ; ----------------------------------;
544 MOV #2,S ; prepare no such file error
545 MOV #0,W ; init entries count
546 ; ----------------------------------;
547 OPN_SearchEntryInSector ; <=== DIR Entry loopback
548 ; ----------------------------------;
550 .word 0E58h ; 5 RLAM #4,Y --> * 16
552 MOV Y,&EntryOfst ; EntryOfst points to first free entry
553 CMP.B #0,BUFFER(Y) ; free entry ? (end of entries in DIR)
554 JZ OPN_NoSuchFile ; error 2 NoSuchFile, used by create ===>
555 MOV #8,X ; count of chars in entry name
556 OPN_CompareName8chars ;
557 CMP.B @TOS+,BUFFER(Y) ; compare Pathname(char) with DirEntry(char)
558 JNZ OPN_FirstCharMismatch ;
561 JNZ OPN_CompareName8chars ; loopback if chars 1 to 7 of stringZ and DirEntry are equal
562 ADD #1,TOS ; 9th char of Pathname is always a dot
563 ; ----------------------------------;
564 OPN_FirstCharMismatch ;
565 CMP.B #'.',-1(TOS) ; FirstNotEqualChar of Pathname = dot ?
567 ; ----------------------------------;
569 ; ----------------------------------;
570 ADD #3,X ; for next cases not equal chars of entry until 11 must be spaces
571 CALL #ParseEntryNameSpaces ; for X + 3 chars
572 JNZ OPN_EntryMismatch ; if a char entry <> space
574 CMP.B #5Ch,-1(TOS) ; FirstNotEqualChar of Pathname = "\" ?
576 OPN_EndOfStringZtest ;
577 CMP.B #0,-1(TOS) ; FirstNotEqualChar of Pathname = 0 ?
579 ; ----------------------------------;
581 ; ----------------------------------;
582 MOV &pathname,TOS ; reload Pathname
584 CMP #16,W ; 16 entry in a sector
585 JNZ OPN_SearchEntryInSector ; ===> loopback for search same sector next entry
586 ; ----------------------------------;
589 ; SUB #1,0(PSP) ; dec count of Dir sectors
590 SUB #1,rDODOES ; dec count of Dir sectors
591 JNZ OPN_LoadSectorDir ; ===> loopback for next DIR sector
592 ; ----------------------------------;
594 JMP OPN_EndOfDIR ; error 4 ===>
595 ; ----------------------------------;
597 ; ----------------------------------;
598 OPN_DotFound ; not equal chars of entry name until 8 must be spaces
599 ; ----------------------------------;
600 CMP.B #'.',-2(TOS) ; LastCharEqual = dot ?
601 JZ OPN_EntryMismatch ; case of first DIR entry = "." and Pathname = "..\"
602 CALL #ParseEntryNameSpaces ; parse X spaces, X{0,...,7}
603 JNZ OPN_EntryMismatch ; if a char entry <> space
605 OPN_CompareExtChars ;
606 CMP.B @TOS+,BUFFER(Y) ; compare stringZ(char) with DirEntry(char)
607 JNZ OPN_ExtNotEqualChar ;
610 JNZ OPN_CompareExtChars ; nothing to do if chars equal
612 OPN_ExtNotEqualChar ;
614 JNZ OPN_EntryMismatch ;
615 CMP.B #5Ch,-1(TOS) ; FirstNotEqualChar = "\" ?
616 JNZ OPN_EntryMismatch ;
617 CALL #ParseEntryNameSpaces ; parse X spaces, X{0,...,3}
618 JNZ OPN_EntryMismatch ; if a char entry <> space
619 ; ----------------------------------;
620 OPN_EntryFound ; Y points on the file attribute (11th byte of entry)
621 ; ----------------------------------;
622 MOV &EntryOfst,Y ; reload DIRentry
623 MOV BUFFER+26(Y),&ClusterL ; first clusterL of file
624 MOV BUFFER+20(Y),&ClusterH ; first clusterT of file, always 0 if FAT16
626 BIT.B #10h,BUFFER+11(Y) ; test if Directory or File
628 ; ----------------------------------;
629 OPN_DIRfound ; entry is a DIRECTORY
630 ; ----------------------------------;
631 CMP #0,&ClusterH ; case of ".." entry, when parent directory is root
632 JNZ OPN_DIRfoundNext ;
633 CMP #0,&ClusterL ; case of ".." entry, when parent directory is root
634 JNZ OPN_DIRfoundNext ;
635 MOV &FATtype,&ClusterL ; set cluster as RootDIR cluster
637 CMP.B #0,-1(TOS) ; FirstNotEqualChar = 0 ?
638 JNZ OPN_EndOfDIRstringZtest ; no : FirstNotEqualChar = "\"
639 ; ----------------------------------;
640 OPN_SetCurrentDIR ; -- open_type DIRsector ptr
641 ; ----------------------------------;
642 MOV &ClusterL,&DIRClusterL ;
643 MOV &ClusterH,&DIRclusterH ;
644 ; MOV #THREEDROP,PC ; 3drop
647 ; ----------------------------------;
648 OPN_FileFound ; -- open_type DIRsector ptr
649 ; ----------------------------------;
652 CALL #GetFreeHandle ;STWXY init handle(HDLL_DIRsect,HDLW_DIRofst,HDLL_FirstClus = HDLL_CurClust,HDLL_CurSize)
653 ; ----------------------------------; output : T = CurrentHdl*, S = ReturnError, Y = DIRentry offset
654 OPN_NomoreHandle ; S = error 16
655 OPN_alreadyOpen ; S = error 8
656 OPN_EndOfDIR ; S = error 4
657 OPN_NoSuchFile ; S = error 2
658 OPN_NoPathName ; S = error 1
660 ; ADD #2,PSP ; -- open_type ptr
661 MOV @PSP+,W ; -- ptr W = open_type
662 MOV #xdodoes,rDODOES ; -- open_type ptr
664 ; ----------------------------------; then go to selected OpenType subroutine (OpenType = W register)
667 ; ======================================================================
668 ; LOAD" primitive as part of Open_File
669 ; input from open: S = OpenError, W = open_type, SectorHL = DIRsectorHL,
670 ; Buffer = [DIRsector], ClusterHL = FirstClusterHL
671 ; from open(GetFreeHandle): Y = DIRentry, T = CurrentHdl
672 ; output: nothing else abort on error
673 ; ======================================================================
675 ; ----------------------------------;
677 ; ----------------------------------;
679 JZ OPEN_LOAD_END ; nothing to do
680 ; ----------------------------------;
682 ; ----------------------------------;
683 .IFDEF SD_CARD_READ_WRITE ;
684 CMP.B #-1,W ; open_type = LOAD"
685 JNZ OPEN_QREAD ; next step
687 ; ----------------------------------; here W is free
689 ; ----------------------------------;
690 CMP #0,S ; open file happy end ?
692 MOV #INTLOOP,IP ; return to sender (QUIT) to get new line.
695 ; ----------------------------------;
697 ; ----------------------------------;
698 OPEN_Error ; S= error
699 ; ----------------------------------;
700 ; Error 1 : PathNameNotFound ; S = error 1
701 ; Error 2 : NoSuchFile ; S = error 2
702 ; Error 4 : DIRisFull ; S = error 4
703 ; Error 8 : alreadyOpen ; S = error 8
704 ; Error 16 : NomoreHandle ; S = error 16
705 ; ----------------------------------;
706 mDOCOL ; set ECHO, type Pathname, type #error, type "< OpenError"; no return
708 .byte 11,"< OpenError" ;
711 .word HERE,COUNT,TYPE,SPACE ;
712 .word BRAN,SD_QABORTYES ; to insert S error as flag, no return
713 ; ----------------------------------;