]> git.sur5r.net Git - cc65/commitdiff
Added support for building targetutils.
authorOliver Schmidt <ol.sc@web.de>
Wed, 8 May 2013 23:12:26 +0000 (01:12 +0200)
committerOliver Schmidt <ol.sc@web.de>
Wed, 8 May 2013 23:12:26 +0000 (01:12 +0200)
15 files changed:
libsrc/Makefile
libsrc/apple2/targetutil/Makefile.inc [new file with mode: 0644]
libsrc/apple2/targetutil/loader.cfg [new file with mode: 0644]
libsrc/apple2/targetutil/loader.o [new file with mode: 0644]
libsrc/apple2/targetutil/loader.s [new file with mode: 0644]
libsrc/apple2/targetutil/loader.txt [new file with mode: 0644]
libsrc/geos-apple/targetutil/Makefile.inc [new file with mode: 0644]
libsrc/geos-apple/targetutil/convert.c [new file with mode: 0644]
targetutil/Makefile [deleted file]
targetutil/apple2/Makefile [deleted file]
targetutil/apple2/loader.cfg [deleted file]
targetutil/apple2/loader.s [deleted file]
targetutil/apple2/loader.txt [deleted file]
targetutil/geos-apple/Makefile [deleted file]
targetutil/geos-apple/convert.c [deleted file]

index 6208d37b9058baeb5fb7a74e12bc86363670fa31..ea486499437c5d85aba74d50c0f524baf4e476ad 100644 (file)
@@ -74,6 +74,9 @@ MKINC = $(GEOS) \
         atari   \
         nes
 
+TARGETUTIL = apple2 \
+             geos-apple
+
 GEOSDIRS = common      \
            conio       \
            disk        \
@@ -90,59 +93,65 @@ GEOSDIRS = common      \
 ifeq ($(TARGET),apple2enh)
   OBJPFX = a2
   DRVPFX = a2e
-  DIRS = apple2
+  SRCDIR = apple2
 else
-  DIRS = $(TARGET)
+  SRCDIR = $(TARGET)
 endif
 
+SRCDIRS = $(SRCDIR)
+
 ifeq ($(TARGET),$(filter $(TARGET),$(CBMS)))
-  DIRS += cbm
+  SRCDIRS += cbm
 endif
 
 ifeq ($(TARGET),$(filter $(TARGET),$(GEOS)))
-  DIRS += $(addprefix $(TARGET)/,  $(GEOSDIRS))
-  DIRS += $(addprefix geos-common/,$(GEOSDIRS))
+  SRCDIRS += $(addprefix $(TARGET)/,  $(GEOSDIRS))
+  SRCDIRS += $(addprefix geos-common/,$(GEOSDIRS))
 endif
 
-DIRS += common   \
-        conio    \
-        dbg      \
-        em       \
-        joystick \
-        mouse    \
-        runtime  \
-        serial   \
-        tgi      \
-        zlib
+SRCDIRS += common   \
+           conio    \
+           dbg      \
+           em       \
+           joystick \
+           mouse    \
+           runtime  \
+           serial   \
+           tgi      \
+           zlib
 
-vpath %.s $(DIRS)
-vpath %.c $(DIRS)
+vpath %.s $(SRCDIRS)
+vpath %.c $(SRCDIRS)
 
-OBJS := $(patsubst %.s,%.o,$(foreach dir,$(DIRS),$(wildcard $(dir)/*.s)))
-OBJS += $(patsubst %.c,%.o,$(foreach dir,$(DIRS),$(wildcard $(dir)/*.c)))
+OBJS := $(patsubst %.s,%.o,$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.s)))
+OBJS += $(patsubst %.c,%.o,$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c)))
 
 OBJS := $(addprefix ../wrk/$(TARGET)/,$(sort $(notdir $(OBJS))))
 
 DEPS = $(OBJS:.o=.d)
 
-EXTRA_SRCPAT = $(firstword $(DIRS))/extra/%.s
+EXTRA_SRCPAT = $(SRCDIR)/extra/%.s
 EXTRA_OBJPAT = ../lib/$(TARGET)-%.o
-EXTRA_OBJS := $(patsubst $(EXTRA_SRCPAT),$(EXTRA_OBJPAT),$(wildcard $(firstword $(DIRS))/extra/*.s))
+EXTRA_OBJS := $(patsubst $(EXTRA_SRCPAT),$(EXTRA_OBJPAT),$(wildcard $(SRCDIR)/extra/*.s))
 
 ZPOBJ = ../wrk/$(TARGET)/zeropage.o
 ifeq ($(TARGET),$(filter $(TARGET),$(EXTZP)))
   ZPOBJ += ../wrk/$(TARGET)/extzp.o
 endif
 
-ifeq ($(TARGET),$(filter $(TARGET),$(MKINC)))
-  include $(TARGET)/Makefile.inc
+ifeq ($(SRCDIR),$(filter $(SRCDIR),$(MKINC)))
+  include $(SRCDIR)/Makefile.inc
+endif
+
+ifeq ($(SRCDIR),$(filter $(SRCDIR),$(TARGETUTIL)))
+  include $(SRCDIR)/targetutil/Makefile.inc
 endif
 
 ##########
 
 define DRVTYPE_template
 
-$1_SRCDIR = $$(firstword $$(DIRS))/$1
+$1_SRCDIR = $$(SRCDIR)/$1
 $1_OBJDIR = ../wrk/$$(TARGET)/$1
 $1_DRVDIR = ../$1
 
@@ -158,14 +167,11 @@ $1_STCS = $$(patsubst $$($1_DRVPAT),$$($1_STCPAT),$$($1_DRVS))
 
 $$($1_OBJS): | $$($1_OBJDIR)
 
-$$($1_OBJDIR):
-       @$$(call MKDIR,$$@)
-
 $$($1_DRVPAT): $$($1_OBJPAT) $$(ZPOBJ) | $$($1_DRVDIR)
        @echo $$(TARGET) - $$(@F)
        @$$(LD) -o $$@ -t module $$^
 
-$$($1_DRVDIR):
+$$($1_OBJDIR) $$($1_DRVDIR):
        @$$(call MKDIR,$$@)
 
 $(TARGET): $$($1_DRVS)
@@ -191,17 +197,32 @@ CC = $(if $(wildcard ../bin/cc65*),../bin/cc65,cc65)
 CO = $(if $(wildcard ../bin/co65*),../bin/co65,co65)
 LD = $(if $(wildcard ../bin/ld65*),../bin/ld65,ld65)
 
+##########
+
+define ASSEMBLE_recipe
+
+@echo $(TARGET) - $<
+@$(CA) -t $(TARGET) $(AFLAGS) --create-dep $(@:.o=.d) -o $@ $<
+
+endef
+
+##########
+
+define COMPILE_recipe
+
+@echo $(TARGET) - $<
+@$(CC) -t $(TARGET) $(CFLAGS) --create-dep $(@:.o=.d) -o $(@:.o=.s) $<
+@$(CA) -t $(TARGET) -o $@ $(@:.o=.s)
+
+endef
+
+##########
+
 ../wrk/$(TARGET)/%.o: %.s | ../wrk/$(TARGET)
-       @echo $(TARGET) - $<
-       @$(CA) -t $(TARGET) $(AFLAGS) --create-dep $(@:.o=.d) -o $@ $<
+       $(ASSEMBLE_recipe)
 
 ../wrk/$(TARGET)/%.o: %.c | ../wrk/$(TARGET)
-       @echo $(TARGET) - $<
-       @$(CC) -t $(TARGET) $(CFLAGS) --create-dep $(@:.o=.d) -o $(@:.o=.s) $<
-       @$(CA) -t $(TARGET) -o $@ $(@:.o=.s)
-
-../wrk/$(TARGET):
-       @$(call MKDIR,$@)
+       $(COMPILE_recipe)
 
 $(EXTRA_OBJPAT): $(EXTRA_SRCPAT) | ../lib
        @echo $(TARGET) - $<
@@ -210,7 +231,7 @@ $(EXTRA_OBJPAT): $(EXTRA_SRCPAT) | ../lib
 ../lib/$(TARGET).lib: $(OBJS) | ../lib
        $(AR) a $@ $?
 
-../lib:
+../wrk/$(TARGET) ../lib ../targetutil:
        @$(call MKDIR,$@)
 
 $(TARGET): $(EXTRA_OBJS) ../lib/$(TARGET).lib
diff --git a/libsrc/apple2/targetutil/Makefile.inc b/libsrc/apple2/targetutil/Makefile.inc
new file mode 100644 (file)
index 0000000..37fec5d
--- /dev/null
@@ -0,0 +1,7 @@
+../wrk/$(TARGET)/loader.o: $(SRCDIR)/targetutil/loader.s | ../wrk/$(TARGET)
+       $(ASSEMBLE_recipe)
+
+../targetutil/loader.system: ../wrk/$(TARGET)/loader.o $(SRCDIR)/targetutil/loader.cfg | ../targetutil
+       $(LD) -o $@ -C $(filter %.cfg,$^) $(filter-out %.cfg,$^)
+
+$(TARGET): ../targetutil/loader.system
diff --git a/libsrc/apple2/targetutil/loader.cfg b/libsrc/apple2/targetutil/loader.cfg
new file mode 100644 (file)
index 0000000..aa7a8c4
--- /dev/null
@@ -0,0 +1,17 @@
+#################################################################################
+#                                                                               #      
+# LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt) #
+#                                                                               #
+#################################################################################
+
+MEMORY {
+    MEMORY_2000: start = $2000, size = $0200, file = %O;
+    MEMORY_0300: start = $0300, size = $0100;
+}
+
+SEGMENTS {
+    CODE_2000: load = MEMORY_2000,                    type = ro;
+    DATA_2000: load = MEMORY_2000,                    type = rw;
+    CODE_0300: load = MEMORY_2000, run = MEMORY_0300, type = ro, define = yes;
+    DATA_0300: load = MEMORY_2000, run = MEMORY_0300, type = rw, define = yes;
+}
diff --git a/libsrc/apple2/targetutil/loader.o b/libsrc/apple2/targetutil/loader.o
new file mode 100644 (file)
index 0000000..5c18e0e
Binary files /dev/null and b/libsrc/apple2/targetutil/loader.o differ
diff --git a/libsrc/apple2/targetutil/loader.s b/libsrc/apple2/targetutil/loader.s
new file mode 100644 (file)
index 0000000..71d7914
--- /dev/null
@@ -0,0 +1,234 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;                                                                               ;
+; LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt) ;
+;                                                                               ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+A1L            := $3C
+A1H            := $3D
+STACK          := $0100
+BUF            := $0200
+PATHNAME       := $0280
+MLI            := $BF00
+VERSION                := $FBB3
+RDKEY          := $FD0C
+PRBYTE         := $FDDA
+COUT           := $FDED
+
+QUIT_CALL         = $65
+GET_FILE_INFO_CALL = $C4
+OPEN_CALL         = $C8
+READ_CALL         = $CA
+CLOSE_CALL        = $CC
+FILE_NOT_FOUND_ERR = $46
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+       .import __CODE_0300_SIZE__, __DATA_0300_SIZE__
+       .import __CODE_0300_LOAD__, __CODE_0300_RUN__
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+.segment       "DATA_2000"
+
+GET_FILE_INFO_PARAM:
+               .byte   $0A             ;PARAM_COUNT
+               .addr   PATHNAME        ;PATHNAME
+               .byte   $00             ;ACCESS
+               .byte   $00             ;FILE_TYPE
+FILE_INFO_ADDR:        .word   $0000           ;AUX_TYPE
+               .byte   $00             ;STORAGE_TYPE
+               .word   $0000           ;BLOCKS_USED
+               .word   $0000           ;MOD_DATE
+               .word   $0000           ;MOD_TIME
+               .word   $0000           ;CREATE_DATE
+               .word   $0000           ;CREATE_TIME
+
+OPEN_PARAM:
+               .byte   $03             ;PARAM_COUNT
+               .addr   PATHNAME        ;PATHNAME
+               .addr   MLI - 1024      ;IO_BUFFER
+OPEN_REF:      .byte   $00             ;REF_NUM
+
+LOADING:
+               .byte   $0D
+               .asciiz "Loading "
+
+ELLIPSES:
+               .byte   " ...", $0D, $0D, $00
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+.segment       "DATA_0300"
+
+READ_PARAM:
+               .byte   $04             ;PARAM_COUNT
+READ_REF:      .byte   $00             ;REF_NUM
+READ_ADDR:     .addr   $0000           ;DATA_BUFFER
+               .word   $FFFF           ;REQUEST_COUNT
+               .word   $0000           ;TRANS_COUNT
+
+CLOSE_PARAM:
+               .byte   $01             ;PARAM_COUNT
+CLOSE_REF:     .byte   $00             ;REF_NUM
+
+QUIT_PARAM:
+               .byte   $04             ;PARAM_COUNT
+               .byte   $00             ;QUIT_TYPE
+               .word   $0000           ;RESERVED
+               .byte   $00             ;RESERVED
+               .word   $0000           ;RESERVED
+
+FILE_NOT_FOUND:
+               .asciiz "... File Not Found"
+                               
+ERROR_NUMBER:
+               .asciiz "... Error $"
+
+PRESS_ANY_KEY:
+               .asciiz " - Press Any Key "
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+.segment       "CODE_2000"
+
+       jmp     :+
+       .byte   $EE
+       .byte   $EE
+       .byte   65
+STARTUP:.res   65
+
+       ; Reset stack
+:      ldx     #$FF
+       txs
+
+       ; Relocate CODE_0300 and DATA_0300
+       ldx     #<(__CODE_0300_SIZE__ + __DATA_0300_SIZE__)
+:      lda     __CODE_0300_LOAD__ - 1,x
+       sta     __CODE_0300_RUN__ - 1,x
+       dex
+       bne     :-
+
+       ; Remove ".SYSTEM" from pathname
+       lda     PATHNAME
+       sec
+       sbc     #.strlen(".SYSTEM")
+       sta     PATHNAME
+
+       ; Add trailing '\0' to pathname
+       tax
+       lda     #$00
+       sta     PATHNAME + 1,x
+
+       ; Copy ProDOS startup filename and trailing '\0' to stack
+       ldx     STARTUP
+       lda     #$00
+       beq     :++             ; bra
+:      lda     STARTUP + 1,x
+:      sta     STACK,x
+       dex
+       bpl     :--     
+
+       ; Provide some user feedback
+       lda     #<LOADING
+       ldx     #>LOADING
+       jsr     PRINT
+       lda     #<(PATHNAME + 1)
+       ldx     #>(PATHNAME + 1)
+       jsr     PRINT
+       lda     #<ELLIPSES
+       ldx     #>ELLIPSES
+       jsr     PRINT
+
+       jsr     MLI
+       .byte   GET_FILE_INFO_CALL
+       .word   GET_FILE_INFO_PARAM
+       bcc     :+
+       jmp     ERROR
+
+:      jsr     MLI
+       .byte   OPEN_CALL
+       .word   OPEN_PARAM
+       bcc     :+
+       jmp     ERROR
+
+       ; Copy file reference number
+:      lda     OPEN_REF
+       sta     READ_REF
+       sta     CLOSE_REF
+
+       ; Get load address from aux-type
+       lda     FILE_INFO_ADDR
+       ldx     FILE_INFO_ADDR + 1
+       sta     READ_ADDR
+       stx     READ_ADDR + 1
+
+       ; It's high time to leave this place
+       jmp     __CODE_0300_RUN__
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+.segment       "CODE_0300"
+
+       jsr     MLI
+       .byte   READ_CALL
+       .word   READ_PARAM
+       bcs     ERROR
+
+       jsr     MLI
+       .byte   CLOSE_CALL
+       .word   CLOSE_PARAM
+       bcs     ERROR
+
+       ; Copy REM token and startup filename to BASIC input buffer
+       ldx     #$00
+       lda     #$B2
+       bne     :++             ; bra
+:      inx
+       lda     a:STACK - 1,x
+:      sta     BUF,x
+       bne     :--
+       
+       ; Go for it ...
+       jmp     (READ_ADDR)
+
+PRINT:
+       sta     A1L
+       stx     A1H
+       ldx     VERSION
+       ldy     #$00
+:      lda     (A1L),y
+       beq     :++
+       cpx     #$06            ; //e ?
+       beq     :+
+       cmp     #$60            ; lowercase ?
+        bcc    :+
+        and    #$5F            ; -> uppercase
+:      ora     #$80
+       jsr     COUT
+       iny
+       bne     :--             ; bra
+:      rts
+
+ERROR:
+       cmp     #FILE_NOT_FOUND_ERR
+       bne     :+
+       lda     #<FILE_NOT_FOUND
+       ldx     #>FILE_NOT_FOUND
+       jsr     PRINT
+       beq     :++             ; bra
+:      pha
+       lda     #<ERROR_NUMBER
+       ldx     #>ERROR_NUMBER
+       jsr     PRINT
+       pla
+       jsr     PRBYTE
+:      lda     #<PRESS_ANY_KEY
+       ldx     #>PRESS_ANY_KEY
+       jsr     PRINT
+       jsr     RDKEY
+       jsr     MLI
+       .byte   QUIT_CALL
+       .word   QUIT_PARAM
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/libsrc/apple2/targetutil/loader.txt b/libsrc/apple2/targetutil/loader.txt
new file mode 100644 (file)
index 0000000..d3ec872
--- /dev/null
@@ -0,0 +1,80 @@
+LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt)
+=============================================================================
+
+
+Background
+----------
+
+Apple][ ProDOS 8 system programs (filetype SYS) are always loaded into memory
+starting at location $2000. This poses the problem of how to make efficient
+use of the memory in the range $0800-$2000. The usual approach of relocation
+has two downsides:
+- Relocating e.g. 30 kB from $2000-$9800 to $0800-$8000 takes a considerable
+  amount of time.
+- Really large programs just don't fit into memory when loaded starting at
+  location $2000.
+
+The relocation can be eliminated by loading the major part(s) of the program
+from disk right to the final location by a rather small system program.
+
+LOADER.SYSTEM is such a small program. In fact it's so small that it fits into
+a single block in the ProDOS 8 file system making it a so-called seedling file,
+which are loaded really fast. LOADER.SYSTEM can load cc65 programs into memory
+anywhere in the range $0800-$BB00 (44,75 kB).
+
+
+Usage
+-----
+
+Link the cc65 program to the start address $0803 (or any other address) and
+store it as binary program (filetype BIN). This is in fact no different from
+a binary program to be run by BASIC.SYSTEM's BRUN command in the usual way.
+
+If however the cc65 program isn't run by BASIC.SYSTEM but is rather run by
+LOADER.SYSTEM then it behaves like a system program which means:
+- It uses memory up to the ProDOS 8 system global page located at $BF00.
+- It supports the ProDOS 8 startup file mechanism (mapped to argv[1]).
+- It quits to the ProDOS 8 dispatcher.
+
+Obviously LOADER.SYSTEM has to be told which cc65 program to run. Unfortunately
+the ProDOS 8 dispatcher has no notion of system program parameters so the usual
+approach would have been to make LOADER.SYSTEM bring up yet another menu to
+select the cc65 program to run.
+
+But to allow to select the cc65 program directly from the ProDOS 8 dispatcher
+anyway LOADER.SYSTEM detects the path to the cc65 program from its own path by
+just removing the '.SYSTEM' from its name. So if you want to run the cc65
+program MYPROGRAM you'll need a copy of LOADER.SYSTEM in the same directory
+being renamed to MYPROGRAM.SYSTEM.
+
+This means you will end up with a copy of LOADER.SYSTEM for every cc65 program
+to be run by it. But as LOADER.SYSTEM is a ProDOS 8 seedling file using up only
+a single block in the ProDOS 8 file system this should be no issue.
+
+
+Build
+-----
+
+In case you want to build 'loader.system' from the source code yourself you can
+do so using the following commands:
+
+ca65 loader.s
+ld65 -C loader.cfg -o loader.system loader.o
+
+
+Installation
+------------
+
+The file 'loader.system' as generated by the cc65 linker with the command above
+does NOT include the 4-byte address/length header that is generated for Apple][
+programs by default. This is because ProDOS 8 system programs are always loaded
+into memory starting at location $2000.
+
+The recommended way to transfer 'loader.system' from your native file system to
+a ProDOS 8 file system disk image is to use AppleCommander which is available at
+http://applecommander.sourceforge.net/
+
+If you want to put the file 'loader.system' onto a disk image 'mydisk.dsk' as
+system program MYPROGRAM.SYSTEM you can do so using the following command:
+
+java -jar ac.jar -p mydisk.dsk MYPROGRAM.SYSTEM sys < loader.system
diff --git a/libsrc/geos-apple/targetutil/Makefile.inc b/libsrc/geos-apple/targetutil/Makefile.inc
new file mode 100644 (file)
index 0000000..ff94296
--- /dev/null
@@ -0,0 +1,9 @@
+../wrk/$(TARGET)/convert.o: TARGET = apple2enh
+
+../wrk/$(TARGET)/convert.o: $(SRCDIR)/targetutil/convert.c | ../wrk/$(TARGET)
+       $(COMPILE_recipe)
+
+../targetutil/convert.system: ../wrk/$(TARGET)/convert.o | ../targetutil
+       $(LD) -o $@ -C apple2enh-system.cfg $^ apple2enh.lib
+
+$(TARGET): ../targetutil/convert.system
diff --git a/libsrc/geos-apple/targetutil/convert.c b/libsrc/geos-apple/targetutil/convert.c
new file mode 100644 (file)
index 0000000..ea9273f
--- /dev/null
@@ -0,0 +1,346 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <dirent.h>
+#include <device.h>
+#include <dio.h>
+
+unsigned char info_signature[3] = {3, 21, 63 | 0x80};
+
+dhandle_t dhandle;
+
+struct dir_entry_t {
+    struct {
+        unsigned name_length  :4;
+        unsigned storage_type :4;
+    }             storage_length;
+    char          file_name[15];
+    unsigned char file_type;
+    unsigned      key_pointer;
+    unsigned      blocks_used;
+    unsigned char size[3];
+    unsigned long creation;
+    unsigned char version;
+    unsigned char min_version;
+    unsigned char access;
+    unsigned      aux_type;
+    unsigned long last_mod;
+    unsigned      header_pointer;
+}* dir_entry;
+
+union {
+    unsigned char bytes[512];
+    struct {
+        unsigned      prev_block;
+        unsigned      next_block;
+        unsigned char entries[1];
+    } content;
+} dir_block;
+
+union {
+    unsigned char bytes[512];
+    struct {
+        unsigned char addr_lo[254];
+        unsigned char size_lo[2];
+        unsigned char addr_hi[254];
+        unsigned char size_hi[2];
+    } content;
+} index_block, master_block, vlir_block;
+
+union {
+    unsigned char bytes[512];
+    struct {
+        unsigned           reserved;
+        unsigned char      info_block[254];
+        unsigned char      vlir_records[128];
+        struct dir_entry_t dir_entry;
+    } content;
+} header_block;
+
+
+static void err_exit(char *operation, unsigned char oserr)
+{
+    if (oserr) {
+        fprintf(stderr, "%s - err:%02x - %s",
+                operation, (int)_oserror, _stroserror(_oserror));
+    } else {
+        fprintf(stderr, "%s",
+                operation);
+    }
+    getchar();
+    exit(EXIT_FAILURE);
+}
+
+
+static unsigned get_dir_entry(char* p_name)
+{
+    char*          d_name;
+    char*          f_name;
+    size_t         f_namelen;
+    DIR*           dir;
+    struct dirent* dirent;
+    unsigned       cur_addr;
+    unsigned char  entry_length;
+    unsigned char  entries_per_block;
+    unsigned char  cur_entry;
+
+    /* Split path name into directory name and file name */
+    f_name = strrchr(p_name, '/');
+    if (f_name) {
+        d_name = p_name;
+        *f_name++ = '\0';
+    } else {
+        d_name = ".";
+        f_name = p_name;
+    }
+    f_namelen = strlen(f_name);
+
+    /* Start with high level functions to get handling
+       of relative path and current drive for free */
+    dir = opendir(d_name);
+    if (!dir) {
+        err_exit("opendir", 1);
+    }
+    dirent = readdir(dir);
+    if (!dirent) {
+        err_exit("readdir", 1);
+    }
+
+    /* Field header_pointer directly follows field last_mod */
+    cur_addr = *(unsigned*)(&dirent->d_mtime.hour + 1);
+
+    dhandle = dio_open(getcurrentdevice());
+    if (!dhandle) {
+        err_exit("dio_open", 1);
+    }
+
+    if (dio_read(dhandle, cur_addr, &dir_block)) {
+        err_exit("dio_read.1", 1);
+    }
+
+    /* Get directory entry infos from directory header */
+    entry_length      = dir_block.bytes[0x23];
+    entries_per_block = dir_block.bytes[0x24];
+
+    /* Skip directory header entry */
+    cur_entry = 1;
+
+    do {
+
+        /* Search for next active directory entry */
+        do {
+
+            /* Check if next directory block is necessary */
+            if (cur_entry == entries_per_block) {
+
+                /* Check if another directory block is present */
+                cur_addr = dir_block.content.next_block;
+                if (!cur_addr) {
+                    _mappederrno(0x46);
+                    err_exit("dio_read.2", 1);
+                }
+
+                /* Read next directory block */
+                if (dio_read(dhandle, cur_addr, &dir_block)) {
+                    err_exit("dio_read.3", 1);
+                }
+
+                /* Start with first entry in next block */
+                cur_entry = 0;
+            }
+
+            /* Compute pointer to current entry */
+            dir_entry = (struct dir_entry_t*)(dir_block.content.entries +
+                                              cur_entry * entry_length);
+
+            /* Switch to next entry */
+            ++cur_entry;
+        } while (!dir_entry->storage_length.storage_type);
+
+    } while (dir_entry->storage_length.name_length != f_namelen ||
+             strncasecmp(dir_entry->file_name, f_name, f_namelen));
+
+    return cur_addr;
+}
+
+
+int main(int argc, char* argv[])
+{
+    char          input[80];
+    char*         p_name;
+    unsigned      dir_addr;
+    unsigned      header_addr;
+    unsigned char index;
+    unsigned long size;
+
+    if (argc > 1) {
+        p_name = argv[1];
+    } else {
+        printf("\n"
+               "Apple GEOS Convert 1.0\n"
+               "----------------------\n"
+               "\n"
+               "Pathname:");
+        p_name = gets(input);
+    }
+
+    dir_addr = get_dir_entry(p_name);
+
+    /* Read index block */
+    if (dio_read(dhandle, dir_entry->key_pointer, &index_block)) {
+        err_exit("dio_read.4", 1);
+    }
+
+    /* First pointer is header block */
+    header_addr = index_block.content.addr_lo[0] |
+                  index_block.content.addr_hi[0] << 8;
+
+    /* Read header block */
+    if (dio_read(dhandle, header_addr, &header_block)) {
+        err_exit("dio_read.5", 1);
+    }
+
+    /* Do some sanity check */
+    for (index = 0; index < sizeof(info_signature); ++index) {
+        if (header_block.content.info_block[index] != info_signature[index]) {
+            err_exit("file signature mismatch", 0);
+        }
+    }
+
+    /* Check ProDOS storage type in directory entry template */
+    if (header_block.content.dir_entry.storage_length.storage_type == 2)
+    {
+
+        /* ProDOS sapling file means GEOS Sequential file*/
+        printf("\nSequential file\n");
+
+        /* Remove header block pointer from pointer list */
+        memmove(&index_block.content.addr_lo[0],
+                &index_block.content.addr_lo[1], sizeof(index_block.content.addr_lo) - 1);
+        memmove(&index_block.content.addr_hi[0],
+                &index_block.content.addr_hi[1], sizeof(index_block.content.addr_hi) - 1);
+
+        /* Get file size from ProDOS directory entry template */
+        size = (unsigned long)(header_block.content.dir_entry.size[0])       |
+               (unsigned long)(header_block.content.dir_entry.size[1]) <<  8 |
+               (unsigned long)(header_block.content.dir_entry.size[2]) << 16;
+
+    } else {
+
+        /* ProDOS tree file means GEOS VLIR file */
+        unsigned      vlir_addr;
+        unsigned long vlir_size;
+        unsigned char vlir_blocks;
+        unsigned char record = 0;
+
+        printf("\nVLIR file\n");
+
+        /* Skip header block pointer */
+        index = 1;
+        size  = 0;
+
+        while (1) {
+
+            /* Get next VLIR index pointer from index block */
+            vlir_addr = index_block.content.addr_lo[index] |
+                        index_block.content.addr_hi[index] << 8;
+            ++index;
+
+            /* Check for end of pointer list */
+            if (vlir_addr == 0) {
+                break;
+            }
+
+            /* Check for empty VLIRs */
+            while (header_block.content.vlir_records[record] == 0xFF) {
+
+                /* Add empty VLIR index pointer to to master index block */
+                master_block.content.addr_lo[record] = 0xFF;
+                master_block.content.addr_hi[record] = 0xFF;
+                ++record;
+            }
+
+            /* Add VLIR index pointer to master index block */
+            master_block.content.addr_lo[record] = (unsigned char)(vlir_addr     );
+            master_block.content.addr_hi[record] = (unsigned char)(vlir_addr >> 8);
+            ++record;
+
+            /* Read VLIR index block */
+            if (dio_read(dhandle, vlir_addr, &vlir_block)) {
+                err_exit("dio_read.6", 1);
+            }
+
+            /* Get VLIR size from VLIR index block */
+            vlir_size = (unsigned long)(vlir_block.content.size_lo[1])       |
+                        (unsigned long)(vlir_block.content.size_hi[1]) <<  8 |
+                        (unsigned long)(vlir_block.content.size_lo[0]) << 16 |
+                        (unsigned long)(vlir_block.content.size_hi[0]) << 24;
+
+            printf("VLIR %u size %lu bytes\n", record - 1, vlir_size);
+
+            /* Compute VLIR block size */
+            vlir_blocks = (unsigned char)((vlir_size + 511) / 512);
+
+            /* Copy VLIR block pointers from index block to VLIR index block */
+            memcpy(&vlir_block.content.addr_lo[0],
+                   &index_block.content.addr_lo[index], vlir_blocks);
+            memcpy(&vlir_block.content.addr_hi[0],
+                   &index_block.content.addr_hi[index], vlir_blocks);
+            index += vlir_blocks;
+
+            /* Write back VLIR index block */
+            if (dio_write(dhandle, vlir_addr, &vlir_block)) {
+                err_exit("dio_write.1", 1);
+            }
+
+            /* Add VLIR size to file size */
+            size += vlir_size;
+        }
+
+        /* Replace (by now completely read) index block with
+           (by now completely created) master index block */
+        index_block = master_block;
+    }
+
+    printf("File size %lu bytes\n\n", size);
+
+    /* Set file size in index block */
+    index_block.content.size_lo[1] = (unsigned char)(size      );
+    index_block.content.size_hi[1] = (unsigned char)(size >>  8);
+    index_block.content.size_lo[0] = (unsigned char)(size >> 16);
+    index_block.content.size_hi[0] = (unsigned char)(size >> 24);
+
+    /* Write index block */
+    if (dio_write(dhandle, dir_entry->key_pointer, &index_block)) {
+        err_exit("dio_write.2", 1);
+    }
+
+    /* Copy selected fields from directory entry template to directory block */
+    dir_entry->storage_length  = header_block.content.dir_entry.storage_length;
+    memcpy(dir_entry->file_name, header_block.content.dir_entry.file_name, 15);
+    dir_entry->file_type       = header_block.content.dir_entry.file_type;
+    dir_entry->size[0]         = (unsigned char)(size      );
+    dir_entry->size[1]         = (unsigned char)(size >>  8);
+    dir_entry->size[2]         = (unsigned char)(size >> 16);
+    dir_entry->creation        = header_block.content.dir_entry.creation;
+    dir_entry->version         = header_block.content.dir_entry.version;
+    dir_entry->min_version     = header_block.content.dir_entry.min_version;
+    dir_entry->aux_type        = header_addr;
+    dir_entry->last_mod        = header_block.content.dir_entry.last_mod;
+
+    /* Write directory block */
+    if (dio_write(dhandle, dir_addr, &dir_block)) {
+        err_exit("dio_write.3", 1);
+    }
+
+    /* We're done */
+    if (dio_close(dhandle)) {
+        err_exit("dio_close", 1);
+    }
+
+    printf("Convert to '%.*s' successful", dir_entry->storage_length.name_length,
+                                           dir_entry->file_name);
+    getchar();
+    return EXIT_SUCCESS;
+}
diff --git a/targetutil/Makefile b/targetutil/Makefile
deleted file mode 100644 (file)
index ef20b64..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Makefile
-#
-
-# --------------------------------------------------------------------------
-# Programs
-
-# Subdirectories
-SUBDIRS = apple2 geos-apple
-
-# --------------------------------------------------------------------------
-# List of executables. This list could be made target dependent by checking
-# $(SYS).
-
-.PHONY: all
-all:
-       @for DIR in $(SUBDIRS); do \
-           $(MAKE) -C $${DIR} $(MAKEOPTS); \
-       done
-
-.PHONY:        clean
-clean:
-       @for DIR in $(SUBDIRS); do \
-           $(MAKE) -C $${DIR} $(MAKEOPTS) clean; \
-       done
-
-.PHONY:        zap
-zap:
-       @for DIR in $(SUBDIRS); do \
-           $(MAKE) -C $${DIR} $(MAKEOPTS) zap; \
-       done
-
diff --git a/targetutil/apple2/Makefile b/targetutil/apple2/Makefile
deleted file mode 100644 (file)
index 0359618..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-# Makefile
-#
-
-# --------------------------------------------------------------------------
-# Programs
-CC      = ../../src/cc65/cc65
-AS      = ../../src/ca65/ca65
-LD      = ../../src/ld65/ld65
-
-# Directories
-CFGDIR  = ../../src/ld65/cfg
-INCDIR  = ../../include
-LIBDIR  = ../../libsrc
-
-# --------------------------------------------------------------------------
-# List of executables.
-
-EXELIST        =       loader.system
-
-
-# --------------------------------------------------------------------------
-# Targets
-
-
-.PHONY:        all
-all:   $(EXELIST)
-
-
-loader.system: loader.s Makefile
-       $(AS) -t apple2 --forget-inc-paths loader.s
-       $(LD) -o $@ -C loader.cfg loader.o $(LIBDIR)/apple2.lib
-
-
-# --------------------------------------------------------------------------
-# Cleanup rules
-
-.PHONY:        clean
-clean:
-       $(RM) *~ *.map *.o *.lbl
-
-.PHONY:        zap
-zap:   clean
-       $(RM) $(EXELIST)
-
-
-
diff --git a/targetutil/apple2/loader.cfg b/targetutil/apple2/loader.cfg
deleted file mode 100644 (file)
index aa7a8c4..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#################################################################################
-#                                                                               #      
-# LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt) #
-#                                                                               #
-#################################################################################
-
-MEMORY {
-    MEMORY_2000: start = $2000, size = $0200, file = %O;
-    MEMORY_0300: start = $0300, size = $0100;
-}
-
-SEGMENTS {
-    CODE_2000: load = MEMORY_2000,                    type = ro;
-    DATA_2000: load = MEMORY_2000,                    type = rw;
-    CODE_0300: load = MEMORY_2000, run = MEMORY_0300, type = ro, define = yes;
-    DATA_0300: load = MEMORY_2000, run = MEMORY_0300, type = rw, define = yes;
-}
diff --git a/targetutil/apple2/loader.s b/targetutil/apple2/loader.s
deleted file mode 100644 (file)
index 71d7914..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;                                                                               ;
-; LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt) ;
-;                                                                               ;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-A1L            := $3C
-A1H            := $3D
-STACK          := $0100
-BUF            := $0200
-PATHNAME       := $0280
-MLI            := $BF00
-VERSION                := $FBB3
-RDKEY          := $FD0C
-PRBYTE         := $FDDA
-COUT           := $FDED
-
-QUIT_CALL         = $65
-GET_FILE_INFO_CALL = $C4
-OPEN_CALL         = $C8
-READ_CALL         = $CA
-CLOSE_CALL        = $CC
-FILE_NOT_FOUND_ERR = $46
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-       .import __CODE_0300_SIZE__, __DATA_0300_SIZE__
-       .import __CODE_0300_LOAD__, __CODE_0300_RUN__
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-.segment       "DATA_2000"
-
-GET_FILE_INFO_PARAM:
-               .byte   $0A             ;PARAM_COUNT
-               .addr   PATHNAME        ;PATHNAME
-               .byte   $00             ;ACCESS
-               .byte   $00             ;FILE_TYPE
-FILE_INFO_ADDR:        .word   $0000           ;AUX_TYPE
-               .byte   $00             ;STORAGE_TYPE
-               .word   $0000           ;BLOCKS_USED
-               .word   $0000           ;MOD_DATE
-               .word   $0000           ;MOD_TIME
-               .word   $0000           ;CREATE_DATE
-               .word   $0000           ;CREATE_TIME
-
-OPEN_PARAM:
-               .byte   $03             ;PARAM_COUNT
-               .addr   PATHNAME        ;PATHNAME
-               .addr   MLI - 1024      ;IO_BUFFER
-OPEN_REF:      .byte   $00             ;REF_NUM
-
-LOADING:
-               .byte   $0D
-               .asciiz "Loading "
-
-ELLIPSES:
-               .byte   " ...", $0D, $0D, $00
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-.segment       "DATA_0300"
-
-READ_PARAM:
-               .byte   $04             ;PARAM_COUNT
-READ_REF:      .byte   $00             ;REF_NUM
-READ_ADDR:     .addr   $0000           ;DATA_BUFFER
-               .word   $FFFF           ;REQUEST_COUNT
-               .word   $0000           ;TRANS_COUNT
-
-CLOSE_PARAM:
-               .byte   $01             ;PARAM_COUNT
-CLOSE_REF:     .byte   $00             ;REF_NUM
-
-QUIT_PARAM:
-               .byte   $04             ;PARAM_COUNT
-               .byte   $00             ;QUIT_TYPE
-               .word   $0000           ;RESERVED
-               .byte   $00             ;RESERVED
-               .word   $0000           ;RESERVED
-
-FILE_NOT_FOUND:
-               .asciiz "... File Not Found"
-                               
-ERROR_NUMBER:
-               .asciiz "... Error $"
-
-PRESS_ANY_KEY:
-               .asciiz " - Press Any Key "
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-.segment       "CODE_2000"
-
-       jmp     :+
-       .byte   $EE
-       .byte   $EE
-       .byte   65
-STARTUP:.res   65
-
-       ; Reset stack
-:      ldx     #$FF
-       txs
-
-       ; Relocate CODE_0300 and DATA_0300
-       ldx     #<(__CODE_0300_SIZE__ + __DATA_0300_SIZE__)
-:      lda     __CODE_0300_LOAD__ - 1,x
-       sta     __CODE_0300_RUN__ - 1,x
-       dex
-       bne     :-
-
-       ; Remove ".SYSTEM" from pathname
-       lda     PATHNAME
-       sec
-       sbc     #.strlen(".SYSTEM")
-       sta     PATHNAME
-
-       ; Add trailing '\0' to pathname
-       tax
-       lda     #$00
-       sta     PATHNAME + 1,x
-
-       ; Copy ProDOS startup filename and trailing '\0' to stack
-       ldx     STARTUP
-       lda     #$00
-       beq     :++             ; bra
-:      lda     STARTUP + 1,x
-:      sta     STACK,x
-       dex
-       bpl     :--     
-
-       ; Provide some user feedback
-       lda     #<LOADING
-       ldx     #>LOADING
-       jsr     PRINT
-       lda     #<(PATHNAME + 1)
-       ldx     #>(PATHNAME + 1)
-       jsr     PRINT
-       lda     #<ELLIPSES
-       ldx     #>ELLIPSES
-       jsr     PRINT
-
-       jsr     MLI
-       .byte   GET_FILE_INFO_CALL
-       .word   GET_FILE_INFO_PARAM
-       bcc     :+
-       jmp     ERROR
-
-:      jsr     MLI
-       .byte   OPEN_CALL
-       .word   OPEN_PARAM
-       bcc     :+
-       jmp     ERROR
-
-       ; Copy file reference number
-:      lda     OPEN_REF
-       sta     READ_REF
-       sta     CLOSE_REF
-
-       ; Get load address from aux-type
-       lda     FILE_INFO_ADDR
-       ldx     FILE_INFO_ADDR + 1
-       sta     READ_ADDR
-       stx     READ_ADDR + 1
-
-       ; It's high time to leave this place
-       jmp     __CODE_0300_RUN__
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-.segment       "CODE_0300"
-
-       jsr     MLI
-       .byte   READ_CALL
-       .word   READ_PARAM
-       bcs     ERROR
-
-       jsr     MLI
-       .byte   CLOSE_CALL
-       .word   CLOSE_PARAM
-       bcs     ERROR
-
-       ; Copy REM token and startup filename to BASIC input buffer
-       ldx     #$00
-       lda     #$B2
-       bne     :++             ; bra
-:      inx
-       lda     a:STACK - 1,x
-:      sta     BUF,x
-       bne     :--
-       
-       ; Go for it ...
-       jmp     (READ_ADDR)
-
-PRINT:
-       sta     A1L
-       stx     A1H
-       ldx     VERSION
-       ldy     #$00
-:      lda     (A1L),y
-       beq     :++
-       cpx     #$06            ; //e ?
-       beq     :+
-       cmp     #$60            ; lowercase ?
-        bcc    :+
-        and    #$5F            ; -> uppercase
-:      ora     #$80
-       jsr     COUT
-       iny
-       bne     :--             ; bra
-:      rts
-
-ERROR:
-       cmp     #FILE_NOT_FOUND_ERR
-       bne     :+
-       lda     #<FILE_NOT_FOUND
-       ldx     #>FILE_NOT_FOUND
-       jsr     PRINT
-       beq     :++             ; bra
-:      pha
-       lda     #<ERROR_NUMBER
-       ldx     #>ERROR_NUMBER
-       jsr     PRINT
-       pla
-       jsr     PRBYTE
-:      lda     #<PRESS_ANY_KEY
-       ldx     #>PRESS_ANY_KEY
-       jsr     PRINT
-       jsr     RDKEY
-       jsr     MLI
-       .byte   QUIT_CALL
-       .word   QUIT_PARAM
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/targetutil/apple2/loader.txt b/targetutil/apple2/loader.txt
deleted file mode 100644 (file)
index d3ec872..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt)
-=============================================================================
-
-
-Background
-----------
-
-Apple][ ProDOS 8 system programs (filetype SYS) are always loaded into memory
-starting at location $2000. This poses the problem of how to make efficient
-use of the memory in the range $0800-$2000. The usual approach of relocation
-has two downsides:
-- Relocating e.g. 30 kB from $2000-$9800 to $0800-$8000 takes a considerable
-  amount of time.
-- Really large programs just don't fit into memory when loaded starting at
-  location $2000.
-
-The relocation can be eliminated by loading the major part(s) of the program
-from disk right to the final location by a rather small system program.
-
-LOADER.SYSTEM is such a small program. In fact it's so small that it fits into
-a single block in the ProDOS 8 file system making it a so-called seedling file,
-which are loaded really fast. LOADER.SYSTEM can load cc65 programs into memory
-anywhere in the range $0800-$BB00 (44,75 kB).
-
-
-Usage
------
-
-Link the cc65 program to the start address $0803 (or any other address) and
-store it as binary program (filetype BIN). This is in fact no different from
-a binary program to be run by BASIC.SYSTEM's BRUN command in the usual way.
-
-If however the cc65 program isn't run by BASIC.SYSTEM but is rather run by
-LOADER.SYSTEM then it behaves like a system program which means:
-- It uses memory up to the ProDOS 8 system global page located at $BF00.
-- It supports the ProDOS 8 startup file mechanism (mapped to argv[1]).
-- It quits to the ProDOS 8 dispatcher.
-
-Obviously LOADER.SYSTEM has to be told which cc65 program to run. Unfortunately
-the ProDOS 8 dispatcher has no notion of system program parameters so the usual
-approach would have been to make LOADER.SYSTEM bring up yet another menu to
-select the cc65 program to run.
-
-But to allow to select the cc65 program directly from the ProDOS 8 dispatcher
-anyway LOADER.SYSTEM detects the path to the cc65 program from its own path by
-just removing the '.SYSTEM' from its name. So if you want to run the cc65
-program MYPROGRAM you'll need a copy of LOADER.SYSTEM in the same directory
-being renamed to MYPROGRAM.SYSTEM.
-
-This means you will end up with a copy of LOADER.SYSTEM for every cc65 program
-to be run by it. But as LOADER.SYSTEM is a ProDOS 8 seedling file using up only
-a single block in the ProDOS 8 file system this should be no issue.
-
-
-Build
------
-
-In case you want to build 'loader.system' from the source code yourself you can
-do so using the following commands:
-
-ca65 loader.s
-ld65 -C loader.cfg -o loader.system loader.o
-
-
-Installation
-------------
-
-The file 'loader.system' as generated by the cc65 linker with the command above
-does NOT include the 4-byte address/length header that is generated for Apple][
-programs by default. This is because ProDOS 8 system programs are always loaded
-into memory starting at location $2000.
-
-The recommended way to transfer 'loader.system' from your native file system to
-a ProDOS 8 file system disk image is to use AppleCommander which is available at
-http://applecommander.sourceforge.net/
-
-If you want to put the file 'loader.system' onto a disk image 'mydisk.dsk' as
-system program MYPROGRAM.SYSTEM you can do so using the following command:
-
-java -jar ac.jar -p mydisk.dsk MYPROGRAM.SYSTEM sys < loader.system
diff --git a/targetutil/geos-apple/Makefile b/targetutil/geos-apple/Makefile
deleted file mode 100644 (file)
index b2dcc96..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Makefile
-#
-
-# --------------------------------------------------------------------------
-# Programs
-CC      = ../../src/cc65/cc65
-AS      = ../../src/ca65/ca65
-LD      = ../../src/ld65/ld65
-
-# Directories
-CFGDIR  = ../../src/ld65/cfg
-INCDIR  = ../../include
-LIBDIR  = ../../libsrc
-
-# --------------------------------------------------------------------------
-# List of executables.
-
-EXELIST        =       convert.system
-
-
-
-# --------------------------------------------------------------------------
-# Targets
-
-
-.PHONY:        all
-all:   $(EXELIST)
-
-
-convert.system:        convert.c Makefile
-       $(CC) --forget-inc-paths -I $(INCDIR) -t apple2enh -O convert.c
-       $(AS) --forget-inc-paths convert.s
-       $(LD) -o $@ -C $(CFGDIR)/apple2enh-system.cfg convert.o $(LIBDIR)/apple2enh.lib
-
-
-# --------------------------------------------------------------------------
-# Cleanup rules
-
-.PHONY:        clean
-clean:
-       $(RM) *~ *.map *.o *.s *.lbl
-
-.PHONY:        zap
-zap:   clean
-       $(RM) $(EXELIST)
-
-
-
diff --git a/targetutil/geos-apple/convert.c b/targetutil/geos-apple/convert.c
deleted file mode 100644 (file)
index ea9273f..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <dirent.h>
-#include <device.h>
-#include <dio.h>
-
-unsigned char info_signature[3] = {3, 21, 63 | 0x80};
-
-dhandle_t dhandle;
-
-struct dir_entry_t {
-    struct {
-        unsigned name_length  :4;
-        unsigned storage_type :4;
-    }             storage_length;
-    char          file_name[15];
-    unsigned char file_type;
-    unsigned      key_pointer;
-    unsigned      blocks_used;
-    unsigned char size[3];
-    unsigned long creation;
-    unsigned char version;
-    unsigned char min_version;
-    unsigned char access;
-    unsigned      aux_type;
-    unsigned long last_mod;
-    unsigned      header_pointer;
-}* dir_entry;
-
-union {
-    unsigned char bytes[512];
-    struct {
-        unsigned      prev_block;
-        unsigned      next_block;
-        unsigned char entries[1];
-    } content;
-} dir_block;
-
-union {
-    unsigned char bytes[512];
-    struct {
-        unsigned char addr_lo[254];
-        unsigned char size_lo[2];
-        unsigned char addr_hi[254];
-        unsigned char size_hi[2];
-    } content;
-} index_block, master_block, vlir_block;
-
-union {
-    unsigned char bytes[512];
-    struct {
-        unsigned           reserved;
-        unsigned char      info_block[254];
-        unsigned char      vlir_records[128];
-        struct dir_entry_t dir_entry;
-    } content;
-} header_block;
-
-
-static void err_exit(char *operation, unsigned char oserr)
-{
-    if (oserr) {
-        fprintf(stderr, "%s - err:%02x - %s",
-                operation, (int)_oserror, _stroserror(_oserror));
-    } else {
-        fprintf(stderr, "%s",
-                operation);
-    }
-    getchar();
-    exit(EXIT_FAILURE);
-}
-
-
-static unsigned get_dir_entry(char* p_name)
-{
-    char*          d_name;
-    char*          f_name;
-    size_t         f_namelen;
-    DIR*           dir;
-    struct dirent* dirent;
-    unsigned       cur_addr;
-    unsigned char  entry_length;
-    unsigned char  entries_per_block;
-    unsigned char  cur_entry;
-
-    /* Split path name into directory name and file name */
-    f_name = strrchr(p_name, '/');
-    if (f_name) {
-        d_name = p_name;
-        *f_name++ = '\0';
-    } else {
-        d_name = ".";
-        f_name = p_name;
-    }
-    f_namelen = strlen(f_name);
-
-    /* Start with high level functions to get handling
-       of relative path and current drive for free */
-    dir = opendir(d_name);
-    if (!dir) {
-        err_exit("opendir", 1);
-    }
-    dirent = readdir(dir);
-    if (!dirent) {
-        err_exit("readdir", 1);
-    }
-
-    /* Field header_pointer directly follows field last_mod */
-    cur_addr = *(unsigned*)(&dirent->d_mtime.hour + 1);
-
-    dhandle = dio_open(getcurrentdevice());
-    if (!dhandle) {
-        err_exit("dio_open", 1);
-    }
-
-    if (dio_read(dhandle, cur_addr, &dir_block)) {
-        err_exit("dio_read.1", 1);
-    }
-
-    /* Get directory entry infos from directory header */
-    entry_length      = dir_block.bytes[0x23];
-    entries_per_block = dir_block.bytes[0x24];
-
-    /* Skip directory header entry */
-    cur_entry = 1;
-
-    do {
-
-        /* Search for next active directory entry */
-        do {
-
-            /* Check if next directory block is necessary */
-            if (cur_entry == entries_per_block) {
-
-                /* Check if another directory block is present */
-                cur_addr = dir_block.content.next_block;
-                if (!cur_addr) {
-                    _mappederrno(0x46);
-                    err_exit("dio_read.2", 1);
-                }
-
-                /* Read next directory block */
-                if (dio_read(dhandle, cur_addr, &dir_block)) {
-                    err_exit("dio_read.3", 1);
-                }
-
-                /* Start with first entry in next block */
-                cur_entry = 0;
-            }
-
-            /* Compute pointer to current entry */
-            dir_entry = (struct dir_entry_t*)(dir_block.content.entries +
-                                              cur_entry * entry_length);
-
-            /* Switch to next entry */
-            ++cur_entry;
-        } while (!dir_entry->storage_length.storage_type);
-
-    } while (dir_entry->storage_length.name_length != f_namelen ||
-             strncasecmp(dir_entry->file_name, f_name, f_namelen));
-
-    return cur_addr;
-}
-
-
-int main(int argc, char* argv[])
-{
-    char          input[80];
-    char*         p_name;
-    unsigned      dir_addr;
-    unsigned      header_addr;
-    unsigned char index;
-    unsigned long size;
-
-    if (argc > 1) {
-        p_name = argv[1];
-    } else {
-        printf("\n"
-               "Apple GEOS Convert 1.0\n"
-               "----------------------\n"
-               "\n"
-               "Pathname:");
-        p_name = gets(input);
-    }
-
-    dir_addr = get_dir_entry(p_name);
-
-    /* Read index block */
-    if (dio_read(dhandle, dir_entry->key_pointer, &index_block)) {
-        err_exit("dio_read.4", 1);
-    }
-
-    /* First pointer is header block */
-    header_addr = index_block.content.addr_lo[0] |
-                  index_block.content.addr_hi[0] << 8;
-
-    /* Read header block */
-    if (dio_read(dhandle, header_addr, &header_block)) {
-        err_exit("dio_read.5", 1);
-    }
-
-    /* Do some sanity check */
-    for (index = 0; index < sizeof(info_signature); ++index) {
-        if (header_block.content.info_block[index] != info_signature[index]) {
-            err_exit("file signature mismatch", 0);
-        }
-    }
-
-    /* Check ProDOS storage type in directory entry template */
-    if (header_block.content.dir_entry.storage_length.storage_type == 2)
-    {
-
-        /* ProDOS sapling file means GEOS Sequential file*/
-        printf("\nSequential file\n");
-
-        /* Remove header block pointer from pointer list */
-        memmove(&index_block.content.addr_lo[0],
-                &index_block.content.addr_lo[1], sizeof(index_block.content.addr_lo) - 1);
-        memmove(&index_block.content.addr_hi[0],
-                &index_block.content.addr_hi[1], sizeof(index_block.content.addr_hi) - 1);
-
-        /* Get file size from ProDOS directory entry template */
-        size = (unsigned long)(header_block.content.dir_entry.size[0])       |
-               (unsigned long)(header_block.content.dir_entry.size[1]) <<  8 |
-               (unsigned long)(header_block.content.dir_entry.size[2]) << 16;
-
-    } else {
-
-        /* ProDOS tree file means GEOS VLIR file */
-        unsigned      vlir_addr;
-        unsigned long vlir_size;
-        unsigned char vlir_blocks;
-        unsigned char record = 0;
-
-        printf("\nVLIR file\n");
-
-        /* Skip header block pointer */
-        index = 1;
-        size  = 0;
-
-        while (1) {
-
-            /* Get next VLIR index pointer from index block */
-            vlir_addr = index_block.content.addr_lo[index] |
-                        index_block.content.addr_hi[index] << 8;
-            ++index;
-
-            /* Check for end of pointer list */
-            if (vlir_addr == 0) {
-                break;
-            }
-
-            /* Check for empty VLIRs */
-            while (header_block.content.vlir_records[record] == 0xFF) {
-
-                /* Add empty VLIR index pointer to to master index block */
-                master_block.content.addr_lo[record] = 0xFF;
-                master_block.content.addr_hi[record] = 0xFF;
-                ++record;
-            }
-
-            /* Add VLIR index pointer to master index block */
-            master_block.content.addr_lo[record] = (unsigned char)(vlir_addr     );
-            master_block.content.addr_hi[record] = (unsigned char)(vlir_addr >> 8);
-            ++record;
-
-            /* Read VLIR index block */
-            if (dio_read(dhandle, vlir_addr, &vlir_block)) {
-                err_exit("dio_read.6", 1);
-            }
-
-            /* Get VLIR size from VLIR index block */
-            vlir_size = (unsigned long)(vlir_block.content.size_lo[1])       |
-                        (unsigned long)(vlir_block.content.size_hi[1]) <<  8 |
-                        (unsigned long)(vlir_block.content.size_lo[0]) << 16 |
-                        (unsigned long)(vlir_block.content.size_hi[0]) << 24;
-
-            printf("VLIR %u size %lu bytes\n", record - 1, vlir_size);
-
-            /* Compute VLIR block size */
-            vlir_blocks = (unsigned char)((vlir_size + 511) / 512);
-
-            /* Copy VLIR block pointers from index block to VLIR index block */
-            memcpy(&vlir_block.content.addr_lo[0],
-                   &index_block.content.addr_lo[index], vlir_blocks);
-            memcpy(&vlir_block.content.addr_hi[0],
-                   &index_block.content.addr_hi[index], vlir_blocks);
-            index += vlir_blocks;
-
-            /* Write back VLIR index block */
-            if (dio_write(dhandle, vlir_addr, &vlir_block)) {
-                err_exit("dio_write.1", 1);
-            }
-
-            /* Add VLIR size to file size */
-            size += vlir_size;
-        }
-
-        /* Replace (by now completely read) index block with
-           (by now completely created) master index block */
-        index_block = master_block;
-    }
-
-    printf("File size %lu bytes\n\n", size);
-
-    /* Set file size in index block */
-    index_block.content.size_lo[1] = (unsigned char)(size      );
-    index_block.content.size_hi[1] = (unsigned char)(size >>  8);
-    index_block.content.size_lo[0] = (unsigned char)(size >> 16);
-    index_block.content.size_hi[0] = (unsigned char)(size >> 24);
-
-    /* Write index block */
-    if (dio_write(dhandle, dir_entry->key_pointer, &index_block)) {
-        err_exit("dio_write.2", 1);
-    }
-
-    /* Copy selected fields from directory entry template to directory block */
-    dir_entry->storage_length  = header_block.content.dir_entry.storage_length;
-    memcpy(dir_entry->file_name, header_block.content.dir_entry.file_name, 15);
-    dir_entry->file_type       = header_block.content.dir_entry.file_type;
-    dir_entry->size[0]         = (unsigned char)(size      );
-    dir_entry->size[1]         = (unsigned char)(size >>  8);
-    dir_entry->size[2]         = (unsigned char)(size >> 16);
-    dir_entry->creation        = header_block.content.dir_entry.creation;
-    dir_entry->version         = header_block.content.dir_entry.version;
-    dir_entry->min_version     = header_block.content.dir_entry.min_version;
-    dir_entry->aux_type        = header_addr;
-    dir_entry->last_mod        = header_block.content.dir_entry.last_mod;
-
-    /* Write directory block */
-    if (dio_write(dhandle, dir_addr, &dir_block)) {
-        err_exit("dio_write.3", 1);
-    }
-
-    /* We're done */
-    if (dio_close(dhandle)) {
-        err_exit("dio_close", 1);
-    }
-
-    printf("Convert to '%.*s' successful", dir_entry->storage_length.name_length,
-                                           dir_entry->file_name);
-    getchar();
-    return EXIT_SUCCESS;
-}