mirror of
https://github.com/cc65/cc65.git
synced 2025-01-21 15:32:41 +00:00
Apple2: Rewrite opendir in assembly
58 bytes size gain
This commit is contained in:
parent
394d3b1964
commit
819a314508
15
libsrc/apple2/dir.inc
Normal file
15
libsrc/apple2/dir.inc
Normal 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
|
@ -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
156
libsrc/apple2/opendir.s
Normal 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
|
Loading…
x
Reference in New Issue
Block a user