1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-26 08:32:00 +00:00

Merge pull request #2533 from colinleroy/apple2-rewrite-opendir-asm

Apple2: Rewrite opendir in assembly
This commit is contained in:
Bob Andrews 2024-11-09 19:35:48 +01:00 committed by GitHub
commit e07cdd0a80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 171 additions and 112 deletions

15
libsrc/apple2/dir.inc Normal file
View File

@ -0,0 +1,15 @@
.struct DIR
FD .word
ENTRY_LENGTH .byte
ENTRIES_PER_BLOCK .byte
CURRENT_ENTRY .byte
.union
BYTES .byte 512
.struct CONTENT
PREV_BLOCK .word
NEXT_BLOCK .word
ENTRIES .byte
.endstruct
.endunion
.endstruct

View File

@ -1,112 +0,0 @@
/*****************************************************************************/
/* */
/* opendir.h */
/* */
/* Open 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 <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include "dir.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
extern char _cwd[FILENAME_MAX];
/*****************************************************************************/
/* Code */
/*****************************************************************************/
DIR* __fastcall__ opendir (register const char* name)
{
register DIR* dir;
/* Alloc DIR */
if ((dir = malloc (sizeof (*dir))) == NULL) {
/* May not have been done by malloc() */
_directerrno (ENOMEM);
/* Return failure */
return NULL;
}
/* Interpret dot as current working directory */
if (*name == '.') {
name = _cwd;
}
/* Open directory file */
if ((dir->fd = open (name, O_RDONLY)) != -1) {
/* Read directory key block */
if (read (dir->fd,
dir->block.bytes,
sizeof (dir->block)) == sizeof (dir->block)) {
/* Get directory entry infos from directory header */
dir->entry_length = dir->block.bytes[0x23];
dir->entries_per_block = dir->block.bytes[0x24];
/* Skip directory header entry */
dir->current_entry = 1;
/* Return success */
return dir;
}
/* EOF: Most probably no directory file at all */
if (_oserror == 0) {
_directerrno (EINVAL);
}
/* Cleanup directory file */
close (dir->fd);
}
/* Cleanup DIR */
free (dir);
/* Return failure */
return NULL;
}

156
libsrc/apple2/opendir.s Normal file
View File

@ -0,0 +1,156 @@
;
; Colin Leroy-Mira <colin@colino.net>, 2024
;
; DIR* __fastcall__ opendir (register const char* name)
;
.export _opendir
.import _open, _read, _close
.import _malloc, _free
.import ___directerrno
.import ___oserror, __cwd
.import pushptr1, popptr1
.import pushax, pusha0
.importzp ptr1
.include "apple2.inc"
.include "dir.inc"
.include "errno.inc"
.include "fcntl.inc"
.include "zeropage.inc"
.proc _opendir
sta ptr1
stx ptr1+1
ldy #$00
lda (ptr1),y
cmp #'.'
bne :+
lda #<__cwd
ldx #>__cwd
sta ptr1
stx ptr1+1
: ; open directory
jsr pushptr1
lda #O_RDONLY
jsr pusha0
ldy #$04
jsr _open
cmp #$FF ; Did we succeed?
beq @return_null
pha ; Yes - Push fd for backup
; malloc the dir struct
lda #<.sizeof(DIR)
ldx #>.sizeof(DIR)
jsr _malloc
bne :+
; We failed to allocate
pla ; Get fd back
ldx #$00
jsr _close ; close it
lda #ENOMEM ; Set error
jsr ___directerrno
@return_null:
lda #$00
tax
rts
: ; 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
sta (ptr1),y
dey
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
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
@read_ok:
; Read succeeded, populate dir struct
jsr popptr1 ; Restore our dir pointer
ldy #$24 + DIR::BYTES
lda (ptr1),y ; ENTRIES_PER_BLOCK
pha ; Back it up
dey
lda (ptr1),y ; ENTRY_LENGTH
ldy #DIR::ENTRY_LENGTH
sta (ptr1),y
pla
.assert DIR::ENTRIES_PER_BLOCK = DIR::ENTRY_LENGTH + 1, error
iny
sta (ptr1),y
; Skip directory header entry
.assert DIR::CURRENT_ENTRY = DIR::ENTRIES_PER_BLOCK + 1, error
iny
lda #$01
sta (ptr1),y
; Return pointer to dir struct
lda ptr1
ldx ptr1+1
rts
.endproc