diff --git a/libsrc/apple2/closedir.c b/libsrc/apple2/closedir.c
deleted file mode 100644
index d37d15bba7..0000000000
--- a/libsrc/apple2/closedir.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*****************************************************************************/
-/* */
-/* closedir.c */
-/* */
-/* Close a directory */
-/* */
-/* */
-/* */
-/* (C) 2005 Oliver Schmidt,
*/
-/* */
-/* */
-/* This software is provided 'as-is', without any expressed or implied */
-/* warranty. In no event will the authors be held liable for any damages */
-/* arising from the use of this software. */
-/* */
-/* Permission is granted to anyone to use this software for any purpose, */
-/* including commercial applications, and to alter it and redistribute it */
-/* freely, subject to the following restrictions: */
-/* */
-/* 1. The origin of this software must not be misrepresented; you must not */
-/* claim that you wrote the original software. If you use this software */
-/* in a product, an acknowledgment in the product documentation would be */
-/* appreciated but is not required. */
-/* 2. Altered source versions must be plainly marked as such, and must not */
-/* be misrepresented as being the original software. */
-/* 3. This notice may not be removed or altered from any source */
-/* distribution. */
-/* */
-/*****************************************************************************/
-
-
-
-#include
-#include
-#include
-#include "dir.h"
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-int __fastcall__ closedir (DIR* dir)
-{
- int result;
-
- /* Cleanup directory file */
- result = close (dir->fd);
-
- /* Cleanup DIR */
- free (dir);
-
- return result;
-}
diff --git a/libsrc/apple2/closedir.s b/libsrc/apple2/closedir.s
new file mode 100644
index 0000000000..1f176092b9
--- /dev/null
+++ b/libsrc/apple2/closedir.s
@@ -0,0 +1,35 @@
+;
+; Colin Leroy-Mira , 2024
+;
+; int __fastcall__ closedir (DIR *dir)
+;
+
+ .export _closedir, closedir_ptr1
+
+ .import _close
+ .import _free
+ .import pushax, popax, pushptr1, swapstk
+
+ .importzp ptr1
+
+ .include "apple2.inc"
+ .include "dir.inc"
+ .include "errno.inc"
+ .include "fcntl.inc"
+ .include "zeropage.inc"
+
+_closedir:
+ sta ptr1
+ stx ptr1+1
+closedir_ptr1:
+ ; Close fd
+ jsr pushptr1 ; Backup ptr1
+ ldy #$00
+ lda (ptr1),y ; Get fd
+ ldx #$00
+ jsr _close
+ jsr swapstk ; Store result, pop ptr1
+
+ ; Free dir structure
+ jsr _free
+ jmp popax ; Return result
diff --git a/libsrc/apple2/opendir.s b/libsrc/apple2/opendir.s
index 38110b6809..317be2755a 100644
--- a/libsrc/apple2/opendir.s
+++ b/libsrc/apple2/opendir.s
@@ -4,16 +4,18 @@
; DIR* __fastcall__ opendir (register const char* name)
;
- .export _opendir
+ .export _opendir, read_dir_block_ptr1
+ .import closedir_ptr1
.import _open, _read, _close
- .import _malloc, _free
+ .import _malloc
.import ___directerrno
.import ___oserror, __cwd
.import pushptr1, popptr1
.import pushax, pusha0
+ .import return0, returnFFFF
.importzp ptr1
@@ -37,7 +39,7 @@
sta ptr1
stx ptr1+1
-: ; open directory
+: ; Open directory
jsr pushptr1
lda #O_RDONLY
jsr pusha0
@@ -58,23 +60,17 @@
; We failed to allocate
pla ; Get fd back
ldx #$00
- jsr _close ; close it
+ jsr _close ; Close it
lda #ENOMEM ; Set error
jsr ___directerrno
-
@return_null:
- lda #$00
- tax
- rts
+ jmp return0
: ; Store dir struct to pointer
sta ptr1
stx ptr1+1
- ; Push ptr1, read will destroy it
- jsr pushptr1
-
; Save fd to dir struct
lda #$00
ldy #DIR::FD + 1
@@ -84,49 +80,15 @@
pla ; Get fd back
sta (ptr1),y
- jsr pusha0 ; push fd for read
- lda #DIR::BYTES
- adc ptr1+1
- tax
- pla
- jsr pushax ; Push dir->block.bytes for read
-
- lda #<.sizeof(DIR::BYTES)
- ldx #>.sizeof(DIR::BYTES)
-
- jsr _read ; Read directory block
- cpx #>.sizeof(DIR::BYTES)
- bne @err_read
- cmp #<.sizeof(DIR::BYTES)
- beq @read_ok
-
-@err_read:
- ; Read failed, exit
- lda ___oserror
- bne :+
- lda #EINVAL
- jsr ___directerrno
-
-: ; Close fd
- jsr popptr1 ; Restore our dir pointer
- ldy #$00
- lda (ptr1),y ; Get fd
- ldx #$00
- jsr _close
+ jsr read_dir_block_ptr1
+ bcc @read_ok
- ; Free dir structure
- lda ptr1
- ldx ptr1+1
- jsr _free
- jmp @return_null
+ ; Close directory, free it
+ jsr closedir_ptr1
+ jmp return0 ; Return NULL
@read_ok:
; Read succeeded, populate dir struct
- jsr popptr1 ; Restore our dir pointer
; Get file_count to entry_length from block
ldy #$26 + DIR::BYTES
@@ -153,3 +115,45 @@
ldx ptr1+1
rts
.endproc
+
+; Read a directory for the DIR* pointer in ptr1
+; Return with carry clear on success
+read_dir_block_ptr1:
+ ; Push ptr1, read will destroy it
+ jsr pushptr1
+
+ ldy #DIR::FD
+ lda (ptr1),y
+
+ jsr pusha0 ; Push fd for read
+ lda #DIR::BYTES
+ adc ptr1+1
+ tax
+ pla
+ jsr pushax ; Push dir->block.bytes for read
+
+ lda #<.sizeof(DIR::BYTES)
+ ldx #>.sizeof(DIR::BYTES)
+
+ jsr _read ; Read directory block
+ cpx #>.sizeof(DIR::BYTES)
+ bne @read_err
+ cmp #<.sizeof(DIR::BYTES)
+ beq @read_ok
+
+@read_err:
+ ; Read failed, exit
+ lda ___oserror
+ bne :+
+ lda #EINVAL
+ jsr ___directerrno
+: sec
+ bcs @out
+@read_ok:
+ clc
+@out:
+ jmp popptr1
diff --git a/libsrc/apple2/readdir.c b/libsrc/apple2/readdir.c
deleted file mode 100644
index 8acfbbe8b7..0000000000
--- a/libsrc/apple2/readdir.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*****************************************************************************/
-/* */
-/* readdir.c */
-/* */
-/* Read directory entry */
-/* */
-/* */
-/* */
-/* (C) 2005 Oliver Schmidt, */
-/* */
-/* */
-/* This software is provided 'as-is', without any expressed or implied */
-/* warranty. In no event will the authors be held liable for any damages */
-/* arising from the use of this software. */
-/* */
-/* Permission is granted to anyone to use this software for any purpose, */
-/* including commercial applications, and to alter it and redistribute it */
-/* freely, subject to the following restrictions: */
-/* */
-/* 1. The origin of this software must not be misrepresented; you must not */
-/* claim that you wrote the original software. If you use this software */
-/* in a product, an acknowledgment in the product documentation would be */
-/* appreciated but is not required. */
-/* 2. Altered source versions must be plainly marked as such, and must not */
-/* be misrepresented as being the original software. */
-/* 3. This notice may not be removed or altered from any source */
-/* distribution. */
-/* */
-/*****************************************************************************/
-
-
-
-#include
-#include
-#include
-#include "dir.h"
-
-
-
-/*****************************************************************************/
-/* Code */
-/*****************************************************************************/
-
-
-
-struct dirent* __fastcall__ readdir (register DIR* dir)
-{
- register unsigned char* entry;
-
- /* Search for the next active directory entry */
- do {
-
- /* Read next directory block if necessary */
- if (dir->current_entry == dir->entries_per_block) {
- if (read (dir->fd,
- dir->block.bytes,
- sizeof (dir->block)) != sizeof (dir->block)) {
-
- /* Just return failure as read() has */
- /* set errno if (and only if) no EOF */
- return NULL;
- }
-
- /* Start with first entry in next block */
- dir->current_entry = 0;
- }
-
- /* Compute pointer to current entry */
- entry = dir->block.content.entries +
- dir->current_entry * dir->entry_length;
-
- /* Switch to next entry */
- ++dir->current_entry;
- } while (entry[0x00] == 0);
-
- /* Move creation date/time to allow for next step below */
- *(unsigned long*)&entry[0x1A] = *(unsigned long*)&entry[0x18];
-
- /* Feature unsigned long access to EOF by extension from 3 to 4 bytes */
- entry[0x18] = 0;
-
- /* Move file type to allow for next step below */
- entry[0x19] = entry[0x10];
-
- /* Zero-terminate file name */
- entry[0x01 + (entry[0x00] & 0x0F)] = 0;
-
- /* Return success */
- return (struct dirent*)&entry[0x01];
-}
diff --git a/libsrc/apple2/readdir.s b/libsrc/apple2/readdir.s
new file mode 100644
index 0000000000..e748055e15
--- /dev/null
+++ b/libsrc/apple2/readdir.s
@@ -0,0 +1,113 @@
+;
+; Colin Leroy-Mira , 2024
+;
+; struct dirent * __fastcall__ readdir (DIR *dir)
+;
+ .export _readdir
+ .import read_dir_block_ptr1
+
+ .import incax1, return0
+ .import tosaddax, tosumula0, incaxy
+ .import pushax, pusha0, pushptr1, popptr1
+ .importzp ptr1, ptr4
+
+ .include "dir.inc"
+
+.proc _readdir
+ sta ptr1
+ stx ptr1+1
+
+@next_entry:
+ ; Do we need to read the next directory block?
+ ldy #DIR::CURRENT_ENTRY
+ lda (ptr1),y
+ ldy #DIR::ENTRIES_PER_BLOCK
+ cmp (ptr1),y
+ bne @read_entry ; We don't
+
+ jsr read_dir_block_ptr1
+ bcc @read_ok
+
+ ; We had a read error
+ jmp return0
+
+@read_ok:
+ ldy #DIR::CURRENT_ENTRY
+ lda #$00
+ sta (ptr1),y
+
+@read_entry:
+ ; Compute pointer to current entry:
+ ; entry = dir->block.content.entries +
+ ; dir->current_entry * dir->entry_length
+
+ jsr pushptr1 ; Backup ptr1
+ lda ptr1
+ ldx ptr1+1
+ ldy #DIR::BYTES + DIR::CONTENT::ENTRIES
+ jsr incaxy
+ jsr pushax
+ ldy #DIR::CURRENT_ENTRY
+ lda (ptr1),y
+ jsr pusha0
+ ldy #DIR::ENTRY_LENGTH
+ lda (ptr1),y
+ jsr tosumula0
+ jsr tosaddax
+ ; Store pointer to current entry
+ sta ptr4
+ stx ptr4+1
+ jsr popptr1
+
+ ; Switch to next entry
+ ldy #DIR::CURRENT_ENTRY
+ lda (ptr1),y
+ clc
+ adc #1
+ sta (ptr1),y
+
+ ; Check if entry[0] == 0
+ ldy #$00
+ lda (ptr4),y
+ beq @next_entry ; Yes, skip entry
+
+ ; Move creation date/time to allow for next step below
+ ; 18-19-1A-1B => 1A-1B-1C-1D
+ ldy #$1B
+: lda (ptr4),y
+ iny
+ iny
+ sta (ptr4),y
+ dey
+ dey
+ dey
+ cpy #$17
+ bne :-
+
+ ; Feature unsigned long access to EOF by extension from 3 to 4 bytes
+ ; entry[0x18] = 0
+ iny
+ lda #$00
+ sta (ptr4),y
+
+ ; Move file type to allow for next step below
+ ; entry[0x19] = entry[0x10]
+ ldy #$10
+ lda (ptr4),y
+ ldy #$19
+ sta (ptr4),y
+
+ ; Zero-terminate file name
+ ldy #$00
+ lda (ptr4),y
+ and #$0F
+ tay
+ iny
+ lda #$00
+ sta (ptr4),y
+
+ ; Return pointer to entry+1
+ lda ptr4
+ ldx ptr4+1
+ jmp incax1
+.endproc