1 ; -*- coding: utf-8 -*-
2 ; forthMSP430FR_SD_LOAD.asm
4 ; Tested with MSP-EXP430FR5994 launchpad
5 ; Copyright (C) <2019> <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 ; used variables : BufferPtr, BufferLen
23 ;-----------------------------------------------------------------------
24 ; SD card OPEN, LOAD subroutines
25 ;-----------------------------------------------------------------------
27 ; rules for registers use
29 ; T = CurrentHdl, pathname
30 ; W = SectorL, (RTC) TIME
31 ; X = SectorH, (RTC) DATE
32 ; Y = BufferPtr, (DIR) EntryOfst, FAToffset
35 ; ----------------------------------;
36 HDLCurClusToFAT1sectWofstY ;WXY Input: T=currentHandle, Output: W=FATsector, Y=FAToffset, Cluster=HDL_CurCluster
37 ; ----------------------------------;
38 MOV HDLL_CurClust(T),&ClusterL ;
39 MOV HDLH_CurClust(T),&ClusterH ;
40 ; ----------------------------------;
41 ClusterToFAT1sectWofstY ;WXY Input : Cluster ; Output: W = FATsector, Y = FAToffset
42 ; ----------------------------------;
43 MOV.B &ClusterL+1,W ;3 W = ClusterLoHI
44 MOV.B &ClusterL,Y ;3 Y = ClusterLoLo
45 CMP #1,&FATtype ;3 FAT16?
48 ; input : Cluster n, max = 7FFFFF (SDcard up to 256 GB)
49 ; ClusterLoLo*4 = displacement in 512 bytes sector ==> FAToffset
50 ; ClusterHiLo&ClusterLoHi +C << 1 = relative FATsector + orgFAT1 ==> FATsector
51 ; ----------------------------------;
52 MOV.B &ClusterH,X ; X = 0:ClusterHiLo
53 SWPB X ; X = ClusterHiLo:0
54 ADD X,W ; W = ClusterHiLo:ClusterLoHi
55 ; ----------------------------------;
56 SWPB Y ; Y = ClusterLoLo:0
57 ADD Y,Y ;1 Y = ClusterLoLo:0 << 1 + carry for FATsector
58 ADDC W,W ; W = ClusterHiLo:ClusterLoHi << 1 = ClusterHiLo:ClusterL / 128
61 ADD Y,Y ; Y = 0:ClusterLoLo << 1
63 ; ----------------------------------;
67 ; ----------------------------------; Input : Cluster, output: Sector = Cluster_first_sector
68 ComputeClusFrstSect ; If Cluster = 1 ==> RootDirectory ==> SectorL = OrgRootDir
69 ; ----------------------------------; Output: SectorL of Cluster
71 MOV &OrgRootDir,&SectorL ;
72 CMP.B #0,&ClusterH ; clusterH <> 0 ?
73 JNE CCFS_AllOthers ; yes
74 CMP #1,&ClusterL ; clusterHL = 1 ? (FAT16 specificity)
75 JZ CCFS_RET ; yes, sectorL for FAT16 OrgRootDIR is done
77 ; ----------------------------------;
78 .IFDEF MPY ; general case
79 ; ----------------------------------;
80 MOV &ClusterL,&MPY32L ;3
81 MOV &ClusterH,&MPY32H ;3
82 MOV &SecPerClus,&OP2 ;5+3
85 ADD &OrgClusters,&SectorL ;5 OrgClusters = sector of virtual cluster 0, word size
86 ADDC #0,&SectorH ;3 32~
87 ; ----------------------------------;
88 .ELSEIF ; case of no hardware multiplier
89 ; ----------------------------------; Cluster24<<SecPerClus --> ClusFrstSect; SecPerClus = {1,2,4,8,16,32,64}
90 PUSHM #3,W ;5 PUSHM W,X,Y
91 MOV.B &SecPerClus,W ;3 SecPerClus(5-1) = multiplicator
92 MOV &ClusterL,X ;3 Cluster(16-1) --> MULTIPLICANDlo
93 MOV.B &ClusterH,Y ;3 Cluster(24-17) --> MULTIPLICANDhi
96 ADD X,X ;1 (RLA) shift one left MULTIPLICANDlo16
97 ADDC Y,Y ;1 (RLC) shift one left MULTIPLICANDhi8
99 RRA W ;1 shift one right multiplicator
100 JNC CCFS_LOOP ;2 C = 0 loop back
101 CCFS_NEXT ; C = 1, it's done
102 ADD &OrgClusters,X ;3 OrgClusters = sector of virtual_cluster_0, word size
104 MOV X,&SectorL ;3 low result
105 MOV Y,&SectorH ;3 high result
106 POPM #3,W ;5 POPM Y,X,W
107 ; ----------------------------------;32~ + 5~ by 2* shift
109 ; ----------------------------------;
112 ; ----------------------------------;
115 ; ----------------------------------;
116 ComputeHDLcurrentSector ; input: currentHandle, output: Cluster, Sector
117 ; ----------------------------------;
118 MOV HDLL_CurClust(T),&ClusterL;
119 MOV HDLH_CurClust(T),&ClusterH;
120 CALL #ComputeClusFrstSect ;
121 MOV.B HDLB_ClustOfst(T),W ;
125 ; ----------------------------------;
130 ; ----------------------------------; input : X = countdown_of_spaces, Y = name pointer in buffer
131 ParseEntryNameSpaces ;XY
132 ; ----------------------------------; output: Z flag, Y is set after the last space char
135 ; ----------------------------------;
136 ParseEntryNameSpacesLoop ;
137 ; ----------------------------------;
138 CMP.B #32,SD_BUF(Y) ; SPACE ?
139 JNZ PENSL_END ; no: RET
142 JNZ ParseEntryNameSpacesLoop;
145 ; ----------------------------------;
148 ; sequentially load in SD_BUF bytsPerSec bytes of a file opened as read or as load
149 ; if new bufferLen have a size <= BufferPtr, closes the file then RET.
150 ; if previous bufferLen had a size < bytsPerSec, closes the file and reloads previous LOADed file if exist.
151 ; HDLL_CurSize leaves the not yet read size
152 ; All used registers must be initialized.
153 ; ==================================;
154 Read_File ; <== SD_ACCEPT, READ
155 ; ==================================;
157 MOV #0,&BufferPtr ; reset BufferPtr (the buffer is already read)
158 ; ----------------------------------;
159 CMP #bytsPerSec,&BufferLen ;
160 JNZ CloseHandleT ; because this last and incomplete sector is already read
161 SUB #bytsPerSec,HDLL_CurSize(T) ; HDLL_CurSize is decremented of one sector lenght
162 SUBC #0,HDLH_CurSize(T) ;
163 ADD.B #1,HDLB_ClustOfst(T) ; current cluster offset is incremented
164 CMP.B &SecPerClus,HDLB_ClustOfst(T) ; Cluster Bound reached ?
165 JLO SetBufLenAndLoadCurSector ; no
166 ; ----------------------------------;
167 ;SearchNextCluster ; yes
168 ; ----------------------------------;
169 MOV.B #0,HDLB_ClustOfst(T) ; reset Current_Cluster sectors offset
170 CALL #HDLCurClusToFAT1sectWofstY;WXY Output: W=FATsector, Y=FAToffset, Cluster=HDL_CurCluster
171 CALL #ReadFAT1SectorW ;SWX (< 65536)
172 MOV #0,HDLH_CurClust(T) ;
173 MOV SD_BUF(Y),HDLL_CurClust(T) ;
174 CMP #1,&FATtype ; FAT16?
175 JZ SetBufLenAndLoadCurSector ;
176 MOV SD_BUF+2(Y),HDLH_CurClust(T);
177 ; ==================================;
178 SetBufLenAndLoadCurSector ;WXY <== previous handle reLOAD with BufferPtr<>0
179 ; ==================================;
180 MOV #bytsPerSec,&BufferLen ; preset BufferLen
181 CMP #0,HDLH_CurSize(T) ; CurSize > 65535 ?
182 JNZ LoadHDLcurrentSector ; yes
183 CMP HDLL_CurSize(T),&BufferPtr ; BufferPtr >= CurSize ? (BufferPtr = 0 or see RestorePreviousLoadedBuffer)
184 JHS CloseHandleT ; yes
185 CMP #bytsPerSec,HDLL_CurSize(T) ; CurSize >= 512 ?
186 JHS LoadHDLcurrentSector ; yes
187 MOV HDLL_CurSize(T),&BufferLen ; no: adjust BufferLen
188 ; ==================================;
189 LoadHDLcurrentSector ; <=== OPEN_WRITE_APPEND
190 ; ==================================;
191 CALL #ComputeHDLcurrentSector ; use no registers
192 ; ==================================;
194 ; ==================================;
196 MOV &SectorH,X ; High
197 JMP ReadSectorWX ; SWX then RET
198 ; ----------------------------------;
201 ; if first open_load token, save DefaultInputStream
202 ; if other open_load token, decrement token, save previous context
205 ; Input : EntryOfst, Cluster = EntryOfst(HDLL_FirstClus())
206 ; init handle(HDLL_DIRsect,HDLW_DIRofst,HDLL_FirstClus,HDLL_CurClust,HDLL_CurSize)
207 ; Output: Cluster = first Cluster of file, X = CurrentHdl
208 ; ----------------------------------; input : Cluster, EntryOfst
209 GetFreeHandle ;STWXY init handle(HDLL_DIRsect,HDLW_DIRofst,HDLL_FirstClus = HDLL_CurClust,HDLL_CurSize)
210 ; ----------------------------------; output : T = new CurrentHdl
211 MOV #8,S ; prepare file already open error
213 MOV #0,X ; X = init previous handle as 0
214 ; ----------------------------------;
216 ; ----------------------------------;
217 CMP.B #0,HDLB_Token(T) ; free handle ?
218 JZ FreeHandleFound ; yes
220 CMP &ClusterH,HDLH_FirstClus(T);
221 JNE SearchNextHandle ;
222 CMP &ClusterL,HDLL_FirstClus(T);
223 JZ InitHandleRET ; error 8: Already Open abort ===>
225 MOV T,X ; handle is occupied, keep it in X as previous handle
226 ADD #HandleLenght,T ;
228 JNZ SearchHandleLoop ;
229 ADD S,S ; 16 = no more handle error, abort ===>
232 ; ----------------------------------;
233 FreeHandleFound ; T = new handle, X = previous handle
234 ; ----------------------------------;
235 MOV #0,S ; prepare Happy End (no error)
237 MOV X,HDLW_PrevHDL(T) ; link to previous handle
238 ; ----------------------------------;
239 CheckCaseOfPreviousToken ;
240 ; ----------------------------------;
241 CMP #0,X ; existing previous handle?
243 ADD &TOIN,HDLW_BUFofst(X) ; in previous handle, add interpret offset to Buffer offset
244 ; ----------------------------------;
245 CheckCaseOfLoadFileToken ;
246 ; ----------------------------------;
247 CMP.B #0,W ; open_type is LOAD (-1) ?
248 JGE InitHandle ; W>=0, no
249 CMP.B #0,HDLB_Token(X) ; previous token is negative? (open_load type)
251 ADD.B HDLB_Token(X),W ; LOAD token = previous LOAD token -1
252 ; ----------------------------------;
254 ; ----------------------------------;
255 MOV.B W,HDLB_Token(T) ; marks handle as open type: <0=LOAD, 1=READ, 2=WRITE, 4=DEL
256 MOV.B #0,HDLB_ClustOfst(T) ; clear ClustOfst
257 MOV &SectorL,HDLL_DIRsect(T); init handle DIRsectorL
258 MOV &SectorH,HDLH_DIRsect(T);
260 MOV Y,HDLW_DIRofst(T) ; init handle SD_BUF offset of DIR entry
261 MOV SD_BUF+26(Y),HDLL_FirstClus(T); init handle firstcluster of file (to identify file)
262 MOV SD_BUF+20(Y),HDLH_FirstClus(T)
263 MOV SD_BUF+26(Y),HDLL_CurClust(T) ; init handle CurrentCluster
264 MOV SD_BUF+20(Y),HDLH_CurClust(T)
265 MOV SD_BUF+28(Y),HDLL_CurSize(T); init handle LOW currentSizeL
266 MOV SD_BUF+30(Y),HDLH_CurSize(T);
267 MOV #0,&BufferPtr ; reset BufferPtr all type of files
268 CMP.B #2,W ; is a WRITE file handle?
269 JZ ComputeHDLcurrentSector ; = 2, is a WRITE file
270 JGE InitHandleRET ; > 2, is a file to be deleted
271 MOV #0,HDLW_BUFofst(T) ; < 2, is a READ or a LOAD file
273 JZ ReplaceInputBuffer ; case of first loaded file
274 JL SaveBufferContext ; case of other loaded file
275 JMP SetBufLenAndLoadCurSector ; case of READ file
276 ; ----------------------------------;
278 ; ----------------------------------;
279 MOV #SDIB_ORG,&PFACIB ; set SD Input Buffer as Current Input Buffer before return to QUIT
280 MOV #SD_ACCEPT,&PFAACCEPT ; redirect ACCEPT to SD_ACCEPT before return to QUIT
281 ; ----------------------------------;
282 SaveBufferContext ; (see CloseHandleT)
283 ; ----------------------------------;
284 MOV &SOURCE_LEN,HDLW_PrevLEN(T) ; = CPL
285 SUB &TOIN,HDLW_PrevLEN(T) ; PREVLEN = CPL - >IN
286 MOV &SOURCE_ORG,HDLW_PrevORG(T) ; = CIB
287 ADD &TOIN,HDLW_PrevORG(T) ; PrevORG = CIB + >IN
288 JMP SetBufLenAndLoadCurSector ; then RET
289 ; ----------------------------------;
292 ; ----------------------------------;
294 ; ----------------------------------;
295 MOV.B #0,HDLB_Token(T) ; release the handle
296 MOV @T,T ; T = previous handle
297 MOV T,&CurrentHdl ; becomes current handle
299 JZ CloseHandleRet ; if no more handle
300 ; ----------------------------------;
301 RestorePreviousLoadedBuffer ;
302 ; ----------------------------------;
303 MOV HDLW_BUFofst(T),&BufferPtr ; restore previous BufferPtr
304 CALL #SetBufLenAndLoadCurSector ; then reload previous buffer
306 ; ----------------------------------;
308 RET ; Z = 1 if no more handle
309 ; ----------------------------------;
312 ; ==================================;
313 CloseHandleT ; <== CLOSE, Read_File, TERM2SD", OPEN_DEL
314 ; ==================================;
316 CMP #0,T ; no handle?
317 JZ CloseHandleRet ; RET
318 ; ----------------------------------;
319 .IFDEF SD_CARD_READ_WRITE
320 CMP.B #2,HDLB_Token(T) ; opened as write (updated) file ?
321 JNZ TestClosedToken ; no
322 CALL #WriteBuffer ;SWXY
323 CALL #OPWW_UpdateDirectory ;SWXY
325 ; ----------------------------------;
327 ; ----------------------------------;
328 CMP.B #0,HDLB_Token(T) ;
329 ; ----------------------------------;
330 CaseOfAnyReadWriteDelFileIsClosed ; token >= 0
331 ; ----------------------------------;
332 JGE CloseHandleHere ; then RET
333 ; ----------------------------------;
334 CaseOfAnyLoadedFileIsClosed ; -- org' len' R-- QUIT3 dst_ptr dst_len SD_ACCEPT
335 ; ----------------------------------;
336 RestoreSD_ACCEPTContext ;
337 ; ----------------------------------;
338 MOV HDLW_PrevLEN(T),TOS ;
339 MOV HDLW_PrevORG(T),0(PSP) ; -- org len
340 ; ----------------------------------;
342 ; ----------------------------------;
343 ADD #6,RSP ; R-- QUIT3 empties return stack
344 MOV @RSP+,IP ; skip return to SD_ACCEPT
345 ; ----------------------------------;
346 CALL #CloseHandleHere ; Z = 1 if no more handle
347 ; ----------------------------------;
348 CheckFirstLoadedFileIsClosed ;
349 ; ----------------------------------;
350 JZ RestoreDefaultACCEPT ;
351 MOV #NOECHO,PC ; -- org len if return to SD_ACCEPT
352 ; ----------------------------------;
353 RestoreDefaultACCEPT ; if no more handle, first loaded file is closed...
354 ; ----------------------------------;
355 MOV #TIB_ORG,&PFACIB ; restore TIB as Current Input Buffer for next line (next QUIT)
356 MOV #BODYACCEPT,&PFAACCEPT ; restore default ACCEPT for next line (next QUIT)
357 MOV #ECHO,PC ; -- org len if return to Terminal ACCEPT
358 ; ----------------------------------;
361 .IFDEF SD_CARD_READ_WRITE
363 ;-----------------------------------------------------------------------
364 ; SD_READ_WRITE FORTH words
365 ;-----------------------------------------------------------------------
368 ; parse string until " is encountered, convert counted string in String
369 ; then parse string until char '0'.
370 ; media identifiers "A:", "B:" ... are ignored (only one SD_Card),
371 ; char "\" as first one initializes rootDir as SearchDir.
372 ; if file found, if not already open and if free handle...
373 ; ...open the file as read and return the handle in CurrentHdl.
374 ; then load first sector in buffer, bufferLen and bufferPtr are ready for read
375 ; currentHdl keep handle that is flagged as "read".
377 ; to read sequentially next sectors use READ word. A flag is returned : true if file is closed.
378 ; the last sector so is in buffer.
380 ; if pathname is a directory, change current directory.
381 ; if an error is encountered, no handle is set, error message is displayed.
383 ; READ" acts also as CD dos command :
384 ; - READ" a:\misc\" set a:\misc as current directory
385 ; - READ" a:\" reset current directory to root
386 ; - READ" ..\" change to parent directory
388 ; to close all files type : WARM (or COLD, RESET)
390 ; ----------------------------------;
391 FORTHWORDIMM "READ\34" ; immediate
392 ; ----------------------------------;
394 MOV.B #1,W ; W = OpenType
396 ; ----------------------------------;
398 ;Z WRITE" pathame" -- immediate
399 ; open or create the file designed by pathname.
400 ; an error occurs if the file is already opened.
401 ; the last sector of the file is loaded in buffer, and bufferPtr leave the address of the first free byte.
402 ; compile state : compile WRITE" pathname"
403 ; exec state : open or create entry selected by pathname
404 ; ----------------------------------;
405 FORTHWORDIMM "WRITE\34" ; immediate
406 ; ----------------------------------;
408 MOV.B #2,W ; W = OpenType
410 ; ----------------------------------;
413 ;Z DEL" pathame" -- immediate
414 ; compile state : compile DEL" pathname"
415 ; exec state : DELETE entry selected by pathname
417 ; ----------------------------------;
418 FORTHWORDIMM "DEL\34" ; immediate
419 ; ----------------------------------;
421 MOV.B #4,W ; W = OpenType
423 ; ----------------------------------;
427 ; close current handle
428 ; ----------------------------------;
430 ; ----------------------------------;
433 ; ----------------------------------;
435 .ENDIF ; SD_CARD_READ_WRITE
437 ;-----------------------------------------------------------------------
438 ; SD_CARD_LOADER FORTH word
439 ;-----------------------------------------------------------------------
441 ;Z LOAD" pathame" -- immediate
442 ; compile state : compile LOAD" pathname"
443 ; exec state : open a file from SD card via its pathname
444 ; see Open_File primitive for pathname conventions
445 ; the opened file becomes the new input stream for INTERPRET
446 ; this command is recursive, limited only by the count of free handles (up to 8)
447 ; LOAD" acts also as dos command "CD" :
448 ; - LOAD" \misc\" set a:\misc as current directory
449 ; - LOAD" \" reset current directory to root
450 ; - LOAD" ..\" change to parent directory
452 ; ----------------------------------;
453 FORTHWORDIMM "LOAD\34" ; immediate
454 ; ----------------------------------;
455 MOV.B #-1,W ; W = OpenType
456 ; ----------------------------------;
459 ; ======================================================================
460 ; OPEN FILE primitive
461 ; ======================================================================
463 ; primitive for LOAD" READ" CREATE" WRITE" DEL"
464 ; store OpenType on TOS,
465 ; compile state : compile OpenType, compile SQUOTE and the string of provided pathname
466 ; exec state : open a file from SD card via its pathname
467 ; convert counted string found at HERE in a String then parse it
468 ; media identifiers "A:", "B:" ... are ignored (only one SD_Card),
469 ; char "\" as first one initializes rootDir as SearchDir.
470 ; if file found, if not already open and if free handle...
471 ; ...open the file as read and return the handle in CurrentHdl.
472 ; if the pathname is a directory, change current directory, no handle is set.
473 ; if an error is encountered, no handle is set, an error message is displayed.
474 ; ----------------------------------;
476 ; ----------------------------------;
479 MOV W,TOS ; -- Open_type (0=LOAD", 1=READ", 2=WRITE", 4=DEL")
482 ; ----------------------------------;
484 mDOCOL ; if compile state R-- LOAD"_return
485 .word lit,lit,COMMA,COMMA ; compile open_type as literal
486 .word SQUOTE ; compile string_exec + string
487 .word lit,ParenOpen,COMMA ; compile (OPEN)
489 ; ----------------------------------;
491 mDOCOL ; if exec state
492 .word lit,'"',WORDD,COUNT ; -- open_type addr u
495 ; ----------------------------------;
496 ParenOpen ; -- open_type HERE HERE as pathname ptr
497 ; ----------------------------------;
498 MOV @PSP+,rDOCON ; rDOCON = addr = pathname PTR
499 ADD rDOCON,TOS ; TOS = EOS (End Of String) = pathname end
500 .IFDEF SD_CARD_READ_WRITE ;
501 MOV TOS,&EndOfPath ; for WRITE CREATE part
503 ; ----------------------------------;
505 ; ----------------------------------;
507 MOV &DIRClusterL,&ClusterL ;
508 MOV &DIRclusterH,&ClusterH ;
509 CMP rDOCON,TOS ; PTR = EOS ? (end of pathname ?)
510 JZ OPN_NoPathName ; yes: error 1 ===>
511 ; ----------------------------------;
512 CMP.B #':',1(rDOCON) ; A: B: C: ... in pathname ?
513 JNZ OPN_AntiSlashStartTest ; no
514 ADD #2,rDOCON ; yes : skip drive because not used, only one SD_card
515 ; ----------------------------------;
516 OPN_AntiSlashStartTest ;
517 CMP.B #'\\',0(rDOCON) ; "\" as first char ?
518 JNZ OPN_SearchDirSector ; no
519 ADD #1,rDOCON ; yes : skip '\' char
520 MOV &FATtype,&ClusterL ; FATtype = 1 as FAT16 RootDIR, FATtype = 2 = FAT32RootDIR
522 ; ----------------------------------;
523 OPN_EndOfStringTest ; <=== dir found in path
524 ; ----------------------------------;
525 CMP rDOCON,TOS ; PTR = EOS ? (end of pathname ?)
526 JZ OPN_SetCurrentDIR ; yes
527 ; ----------------------------------;
528 OPN_SearchDirSector ;
529 ; ----------------------------------;
530 MOV rDOCON,&Pathname ; save Pathname ptr
531 CALL #ComputeClusFrstSect ; output: SectorHL
532 MOV #32,rDODOES ; preset countdown for FAT16 RootDIR sectors
533 CMP #2,&FATtype ; FAT32?
534 JZ OPN_SetDirSectors ; yes
535 CMP &ClusterL,&FATtype ; FAT16 AND RootDIR ?
536 JZ OPN_LoadDIRsector ; yes
538 MOV &SecPerClus,rDODOES ;
539 ; ----------------------------------;
540 OPN_LoadDIRsector ; <=== 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_SearchDIRentry ; <=== DIR Entry loopback
548 ; ----------------------------------;
552 MOV Y,&EntryOfst ; EntryOfst points to first free entry
553 CMP.B #0,SD_BUF(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 ; ----------------------------------;
557 OPN_CompareName8chars ;
558 ; ----------------------------------;
559 CMP.B @rDOCON+,SD_BUF(Y) ; compare Pathname(char) with DirEntry(char)
560 JNZ OPN_FirstCharMismatch ;
563 JNZ OPN_CompareName8chars ; loopback if chars 1 to 7 of string and DirEntry are equal
564 ADD #1,rDOCON ; 9th char of Pathname is always a dot
565 ; ----------------------------------;
566 OPN_FirstCharMismatch ;
567 CMP.B #'.',-1(rDOCON) ; FirstNotEqualChar of Pathname = dot ?
569 ; ----------------------------------;
571 ; ----------------------------------;
572 ADD #3,X ; for next cases not equal chars of entry until 11 must be spaces
573 CALL #ParseEntryNameSpaces ; for X + 3 chars
574 JNZ OPN_DIRentryMismatch ; if a char entry <> space
575 CMP.B #'\\',-1(rDOCON) ; FirstNotEqualChar of Pathname = "\" ?
577 CMP rDOCON,TOS ; EOS exceeded ?
578 JLO OPN_EntryFound ; yes
579 ; ----------------------------------;
580 OPN_DIRentryMismatch ;
581 ; ----------------------------------;
582 MOV &pathname,rDOCON ; reload Pathname
584 CMP #16,W ; 16 entry in a sector
585 JNZ OPN_SearchDIRentry ; ===> loopback for search next DIR entry
586 ; ----------------------------------;
589 SUB #1,rDODOES ; dec count of Dir sectors
590 JNZ OPN_LoadDIRsector ; ===> loopback for search next DIR sector
591 ; ----------------------------------;
593 JMP OPN_EndOfDIR ; error 4 ===>
594 ; ----------------------------------;
596 ; ----------------------------------;
597 OPN_DotFound ; not equal chars of entry name until 8 must be spaces
598 ; ----------------------------------;
599 CMP.B #'.',-2(rDOCON) ; LastCharEqual = dot ?
600 JZ OPN_DIRentryMismatch ; case of first DIR entry = "." and Pathname = "..\"
601 CALL #ParseEntryNameSpaces ; parse X spaces, X{0,...,7}
602 JNZ OPN_DIRentryMismatch ; if a char entry <> space
604 ; ----------------------------------;
605 OPN_CompareExt3chars ;
606 ; ----------------------------------;
607 CMP.B @rDOCON+,SD_BUF(Y) ; compare string(char) with DirEntry(char)
608 JNZ OPN_ExtNotEqualChar ;
611 JNZ OPN_CompareExt3chars ; nothing to do if chars equal
613 OPN_ExtNotEqualChar ;
614 CMP rDOCON,TOS ; EOS exceeded ?
615 JHS OPN_DIRentryMismatch ; no, loop back
616 CMP.B #'\\',-1(rDOCON) ; FirstNotEqualChar = "\" ?
617 JNZ OPN_DIRentryMismatch ;
618 CALL #ParseEntryNameSpaces ; parse X spaces, X{0,...,3}
619 JNZ OPN_DIRentryMismatch ; if a char entry <> space, loop back
620 ; ----------------------------------;
621 OPN_EntryFound ; Y points on the file attribute (11th byte of entry)
622 ; ----------------------------------;
623 MOV &EntryOfst,Y ; reload DIRentry
624 MOV SD_BUF+26(Y),&ClusterL ; first clusterL of file
625 MOV SD_BUF+20(Y),&ClusterH ; first clusterT of file, always 0 if FAT16
627 BIT.B #10h,SD_BUF+11(Y) ; test if Directory or File
629 ; ----------------------------------;
630 OPN_DIRfound ; entry is a DIRECTORY
631 ; ----------------------------------;
632 CMP #0,&ClusterH ; case of ".." entry, when parent directory is root
633 JNZ OPN_DIRfoundNext ;
634 CMP #0,&ClusterL ; case of ".." entry, when parent directory is root
635 JNZ OPN_DIRfoundNext ;
636 MOV &FATtype,&ClusterL ; set cluster as RootDIR cluster
638 CMP rDOCON,TOS ; EOS exceeded ?
639 JHS OPN_EndOfStringTest ; no: (we presume that FirstNotEqualChar = "\") ==> loop back
640 ; ----------------------------------;
641 OPN_SetCurrentDIR ; -- open_type ptr
642 ; ----------------------------------;
643 MOV &ClusterL,&DIRClusterL ;
644 MOV &ClusterH,&DIRclusterH ;
645 MOV #0,0(PSP) ; -- open_type ptr open_type = 0
647 ; ----------------------------------;
648 OPN_FileFound ; -- open_type ptr
649 ; ----------------------------------;
651 CALL #GetFreeHandle ;STWXY init handle(HDLL_DIRsect,HDLW_DIRofst,HDLL_FirstClus = HDLL_CurClust,HDLL_CurSize)
652 ; ----------------------------------; output : T = CurrentHdl*, S = ReturnError, Y = DIRentry offset
653 OPN_NomoreHandle ; S = error 16
654 OPN_alreadyOpen ; S = error 8
655 OPN_EndOfDIR ; S = error 4
656 OPN_NoSuchFile ; S = error 2
657 OPN_NoPathName ; S = error 1
659 MOV #xdodoes,rDODOES ; restore rDODOES
660 MOV #xdocon,rDOCON ; restore rDODOES
661 MOV @PSP+,W ; -- ptr W = open_type
663 ; ----------------------------------; then go to selected OpenType subroutine (OpenType = W register)
666 ; ======================================================================
667 ; LOAD" primitive as part of Open_File
668 ; input from open: S = OpenError, W = open_type, SectorHL = DIRsectorHL,
669 ; Buffer = [DIRsector], ClusterHL = FirstClusterHL
670 ; from open(GetFreeHandle): Y = DIRentry, T = CurrentHdl
671 ; output: nothing else abort on error
672 ; ======================================================================
674 ; ----------------------------------;
676 ; ----------------------------------;
678 JZ OPEN_LOAD_END ; nothing to do
679 ; ----------------------------------;
681 ; ----------------------------------;
682 .IFDEF SD_CARD_READ_WRITE ;
683 CMP.B #-1,W ; open_type = LOAD"
684 JNZ OPEN_QREAD ; next step
686 ; ----------------------------------; here W is free
688 ; ----------------------------------;
689 CMP #0,S ; open file happy end ?
693 ; ----------------------------------;
695 ; ----------------------------------;
696 OPEN_Error ; S= error
697 ; ----------------------------------;
698 ; Error 1 : PathNameNotFound ; S = error 1
699 ; Error 2 : NoSuchFile ; S = error 2
700 ; Error 4 : DIRisFull ; S = error 4
701 ; Error 8 : alreadyOpen ; S = error 8
702 ; Error 16 : NomoreHandle ; S = error 16
703 ; ----------------------------------;
704 mDOCOL ; set ECHO, type Pathname, type #error, type "< OpenError"; no return
705 .word XSQUOTE ; don't use S register
706 .byte 11,"< OpenError" ;
707 .word BRAN,SD_QABORTYES ; to insert S error as flag, no return
708 ; ----------------------------------;