@@ -294,7 +294,7 @@ createFileEntry:
294294 add c
295295 ld c , a
296296 jr nc , _
297- inc c
297+ inc b
298298_: call cpHLBC
299299 pop bc
300300 jp c , .endOfFilesystem
@@ -414,36 +414,45 @@ _: pop af
414414
415415; Internal function - finds the end of the FAT, swaps that page in, and leaves HL for you to use
416416findFATEnd:
417- ; Find end of FAT
418- ld d , fatStart
419- ld a , d
420- setBankA
421- ld hl , 0x7FFF
417+ push af
418+ push bc
419+ push de
420+ ; Find end of FAT
421+ ld d , fatStart
422+ ld a , d
423+ setBankA
424+ ld hl , 0x7FFF
422425.search:
423- ld a , (hl)
424- cp fsEndOfTable
425- jr z , .endOfTable
426- dec hl
427- ld c , (hl)
428- dec hl
429- ld b , (hl)
430- scf
431- sbc hl , bc ; Skip to next entry
432- ld a , 0x40
433- cp h
434- jr c , .search
435- ; Swap in next page of FAT
436- dec d
437- ld a , d
438- cp fatStart - 4
439- jp z , .exitError
440- setBankA
441- ld hl , 0x7FFF
442- jr .search
426+ ld a , (hl)
427+ cp fsEndOfTable
428+ jr z , .endOfTable
429+ dec hl
430+ ld c , (hl)
431+ dec hl
432+ ld b , (hl)
433+ scf
434+ sbc hl , bc ; Skip to next entry
435+ ld a , 0x40
436+ cp h
437+ jr c , .search
438+ ; Swap in next page of FAT
439+ dec d
440+ ld a , d
441+ cp fatStart - 4
442+ jp z , .exitError
443+ setBankA
444+ ld hl , 0x7FFF
445+ jr .search
443446.endOfTable:
447+ pop de
448+ pop bc
449+ pop af
444450 cp a
445451 ret
446452.exitError:
453+ pop de
454+ pop bc
455+ pop af
447456 or 1
448457 ret
449458
@@ -1002,3 +1011,216 @@ _: pop af
10021011.done:
10031012 pop iy \ pop de \ pop bc \ pop ix \ pop hl
10041013 ret
1014+
1015+ ;; createSymLink [Filesystem]
1016+ ;; Creates a symbolic link.
1017+ ;; Inputs:
1018+ ;; DE: Path to new symlink
1019+ ;; HL: Path to target
1020+ ;; Outputs:
1021+ ;; Z: Set on success, reset on failure
1022+ ;; A: Flash page (on success); error code (on failure)
1023+ ;; HL: Address relative to 0x4000 (on success)
1024+ createSymLink:
1025+ ; Check if node already exists
1026+ ld a , 1
1027+ or a ; Reset Z
1028+ push hl
1029+ call findNode
1030+ jr nz , _
1031+ inc sp \ inc sp
1032+ or 1
1033+ ld a , errAlreadyExists
1034+ ret
1035+ ; Disable interrupts
1036+ _: pop hl
1037+ push af
1038+ ld a , i
1039+ push af
1040+ di
1041+ push bc
1042+ push de
1043+ push hl
1044+ push ix
1045+ ; push target
1046+ push hl
1047+ ; Seperate file path into dir and filename
1048+ ; Inputs:
1049+ ; DE: Path string pointer
1050+ ; Outputs:
1051+ ; BC: Pointer to last /
1052+ push de
1053+ . loop :
1054+ ld a , (de)
1055+ or a
1056+ jr z , .done
1057+ cp '/'
1058+ jr nz , _
1059+ push de \ pop bc
1060+ _: inc de
1061+ jr . loop
1062+ .done:
1063+ pop de
1064+ ; push pointer to last /
1065+ push bc
1066+ ; get length of parent dir
1067+ ld a , c
1068+ sub e
1069+ ld c , a
1070+ ld a , b
1071+ sbc d
1072+ ld b , a
1073+ ; copy parent dir to kernel garbage
1074+ ; TODO: Make sure this spot is safe
1075+ push de \ pop hl
1076+ ld de , kernelGarbage + 0x100
1077+ ldir
1078+ xor a
1079+ ld (de) , a
1080+ ; findNode parent dir, error if not found
1081+ ld de , kernelGarbage + 0x100
1082+ call findNode
1083+ jp nz , .dirNotFound
1084+ ; Begin creating new FS entry
1085+ ; IX = buffer in kernel ram
1086+ ld ix , kernelGarbage + 0x100
1087+ ; Write symlink identifier
1088+ ld (ix) , fsSymLink
1089+ dec ix
1090+ ; Skip entry size until later
1091+ dec ix
1092+ dec ix
1093+ ; write parent ID
1094+ dec hl
1095+ dec hl
1096+ dec hl
1097+ dec hl
1098+ dec hl
1099+ ld a , (hl)
1100+ ld (ix) , a
1101+ dec hl
1102+ dec ix
1103+ ld a , (hl)
1104+ ld (ix) , a
1105+ dec ix
1106+ ; pop pointer to last /
1107+ pop hl
1108+ push hl \ pop de
1109+ ; count length of filename
1110+ ld bc , 0
1111+ _: inc c
1112+ inc de
1113+ ld a , (de)
1114+ or a
1115+ jr nz , - _
1116+ ; TODO: Error if length of filename is 0
1117+ ; write length of filename
1118+ ld (ix) , c
1119+ ; write filename
1120+ _: inc hl
1121+ dec ix
1122+ ld a , (hl)
1123+ ld (ix) , a
1124+ dec c
1125+ ld a , c
1126+ or a
1127+ jr nz , - _
1128+ dec ix
1129+ ; pop and write target
1130+ ; TODO: Error if target length is 0
1131+ pop hl
1132+ _: ld a , (hl)
1133+ ld (ix) , a
1134+ dec ix
1135+ inc hl
1136+ or a
1137+ jr nz , - _
1138+ ; sub IX from start of buffer to get entry length
1139+ push ix \ pop hl
1140+ ld bc , kernelGarbage + 0x0FD
1141+ ld a , c
1142+ sub l
1143+ ld c , a
1144+ ld a , b
1145+ sbc h
1146+ ld b , a
1147+ ; write entry length to buffer-1
1148+ ld hl , kernelGarbage + 0x0FF
1149+ ld (hl) , c
1150+ dec hl
1151+ ld (hl) , b
1152+ ; get location of next entry in FS table
1153+ call findFATEnd
1154+ ; error if no more room in table
1155+ jr nz , .fatFull
1156+ ; subtract entry length from end of FAT
1157+ inc bc
1158+ inc bc
1159+ inc bc
1160+ ld a , l
1161+ sub c
1162+ ld l , a
1163+ ld a , h
1164+ sbc b
1165+ ld h , a
1166+ ; Check for end of flash page
1167+ ; TODO: Stradle flash pages
1168+ push bc
1169+ ld bc , 0x4000
1170+ call cpHLBC
1171+ pop bc
1172+ jp c , .fatFull
1173+ ; write entry to flash
1174+ call unlockFlash
1175+ inc ix
1176+ push ix \ pop de
1177+ ex de , hl
1178+ inc de
1179+ call writeFlashBuffer
1180+ call lockFlash
1181+ ; Return HL with file entry address
1182+ ex de , hl
1183+ add hl , bc
1184+ dec hl
1185+ ; and return A with flash page
1186+ getBankA
1187+ ld (ix + 5 ) , a
1188+ pop ix
1189+ inc sp \ inc sp ; Skip HL
1190+ pop de
1191+ pop bc
1192+ ; Restore interrupts
1193+ pop af
1194+ jp po , _
1195+ ei
1196+ _: pop af
1197+ cp a
1198+ ret
1199+
1200+ .dirNotFound:
1201+ ; pop pointer to last /
1202+ pop bc
1203+ ; pop target
1204+ pop hl
1205+ pop ix
1206+ pop hl
1207+ pop de
1208+ pop bc
1209+ pop af
1210+ jp po , _
1211+ _: pop af
1212+ or 1
1213+ ld a , errFileNotFound
1214+ ret
1215+
1216+ .fatFull:
1217+ pop ix
1218+ pop hl
1219+ pop de
1220+ pop bc
1221+ pop af
1222+ jp po , _
1223+ _: pop af
1224+ or 1
1225+ ld a , errFilesystemFull
1226+ ret
0 commit comments