mirror of
https://github.com/cc65/cc65.git
synced 2025-04-15 19:37:46 +00:00
Apple2: Rewrite readdir() and closedir() to assembly
This commit is contained in:
parent
700c01fa8b
commit
f663ee428d
@ -1,57 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* closedir.c */
|
||||
/* */
|
||||
/* Close a directory */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */
|
||||
/* */
|
||||
/* */
|
||||
/* 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 <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include "dir.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
int __fastcall__ closedir (DIR* dir)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Cleanup directory file */
|
||||
result = close (dir->fd);
|
||||
|
||||
/* Cleanup DIR */
|
||||
free (dir);
|
||||
|
||||
return result;
|
||||
}
|
35
libsrc/apple2/closedir.s
Normal file
35
libsrc/apple2/closedir.s
Normal file
@ -0,0 +1,35 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 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
|
@ -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
|
||||
clc
|
||||
adc ptr1
|
||||
pha
|
||||
lda #>DIR::BYTES
|
||||
adc ptr1+1
|
||||
tax
|
||||
pla
|
||||
jsr pushax ; Push dir->block.bytes for read
|
||||
jsr read_dir_block_ptr1
|
||||
bcc @read_ok
|
||||
|
||||
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
|
||||
|
||||
; 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
|
||||
clc
|
||||
adc ptr1
|
||||
pha
|
||||
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
|
||||
|
@ -1,90 +0,0 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* readdir.c */
|
||||
/* */
|
||||
/* Read directory entry */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */
|
||||
/* */
|
||||
/* */
|
||||
/* 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 <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#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];
|
||||
}
|
113
libsrc/apple2/readdir.s
Normal file
113
libsrc/apple2/readdir.s
Normal file
@ -0,0 +1,113 @@
|
||||
;
|
||||
; Colin Leroy-Mira <colin@colino.net>, 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
|
Loading…
x
Reference in New Issue
Block a user