From b5d754279cef91c49776bb4da250bd69c3d9ae9d Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Fri, 15 Mar 2019 23:22:07 -0400 Subject: port aexec.dasm to ca65, no more dasm build dep --- src/Makefile | 4 +- src/aexec.dasm | 206 --------------------------------------------------------- src/aexec.s | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/loadxex.s | 3 +- 4 files changed, 206 insertions(+), 209 deletions(-) delete mode 100644 src/aexec.dasm create mode 100644 src/aexec.s diff --git a/src/Makefile b/src/Makefile index ba72f9f..5efd335 100644 --- a/src/Makefile +++ b/src/Makefile @@ -45,8 +45,8 @@ loadmenu.xex: loadxex.s loadmkau.xex: loadxex.s cl65 -t none -o loadmkau.xex loadxex.s -aexec.xex: aexec.dasm - dasm aexec.dasm -f3 -oaexec.xex +aexec.xex: aexec.s + cl65 -t none -o aexec.xex aexec.s test: disk atariserver fujitest.atr diff --git a/src/aexec.dasm b/src/aexec.dasm deleted file mode 100644 index 9338c4c..0000000 --- a/src/aexec.dasm +++ /dev/null @@ -1,206 +0,0 @@ - -; Load an Atari DOS executable, including support for init and run vectors -; Parameters: nul-terminated filename pointer in A/X (lo/hi) -; Return value: 0 for success, nonzero on error, never returns if exe has -; a run address. - -; TODO: learn ca65 syntax better, port this to ca65 - -; Usage: build with "dasm aexec.dasm -f3 -oaexec.xex" -; "Link" to your program with "cat aexec.xex yourprog.xex > newprog.xex" - -; int __fastcall__ (*atari_exec_p)(char *) = (int __fastcall__ (*)(char *))0x600; -; #define atari_exec(x) ((*atari_exec_p)(x)) -; then call with: atari_exec("D:PROGRAM.XEX"); - -; If the file can't be opened for whatever reason, atari_exec() returns a -; nonzero result (the Atari error number). - -; If the file loads OK and has a run address, atari_exec() never returns -; (runs the loaded program, then exits to DOS if/when the program exits). -; This means there's no memory conflict between caller and callee. - -; If there was no run address, atari_exec returns 0 to the caller. -; The caller is responsible for making sure the loaded program doesn't -; step on the memory used by the caller or atari_exec itself! - -; If the file is openable but invalid (not a XEX, or truncated), current -; atari_exec() implementation hangs the machine with a red screen, since -; there's no way to know whether the partially-loaded program overwrote -; the caller... - - - processor 6502 - include "equates.inc" - -tmp = $d4 ; aka FR0 -loadaddr = $d6 - -main = $0600 - - org main-6 - word $FFFF - word main - word endmain-1 - - org main - pha - txa - pha - jsr fclose - pla - tax - pla - - sta ICBAL+16 - stx ICBAH+16 - sta tmp - stx tmp+1 - ldy #0 - -; do an OPEN #1,4,0,$filename - -; get length of filename -fnameloop: - lda (tmp),y - beq fndone - iny - bne fnameloop - - ; set IOCB #1 buffer addr, buffer len, etc -fndone: - sty ICBLL+$10 - lda #0 - sta ICBLH+$10 - sta ICAX2+$10 - - ; init these to 0 so we can tell if they change - sta RUNAD - sta RUNAD+1 - sta INITAD - sta INITAD+1 - - ldx #4 - stx ICAX1+$10 - dex - stx ICCOM+$10 ; cmd #3 = OPEN - - ldx #$10 - jsr CIOV ; do the OPEN - bpl readheader - - tya ; CIO returns error code in Y reg - ldx #0 - rts - -fail: - lda #$48 - sta 710 -hang bne hang - -readheader: -; read 2 bytes into local buffer - jsr read2bytes - bpl ok - cpy #136 ; EOF - bne fail - beq close_file ; if at EOF, close the file - -; if they're $ffff, try again -ok: - lda tmp - tax - and tmp+1 - cmp #$ff - beq readheader - -; store those 2 bytes in loadaddr - lda tmp+1 - sta loadaddr+1 - stx loadaddr - -; read 2 more bytes into local buffer (end addr) - jsr read2bytes - bmi fail -; subtract loadaddr from end addr, add 1, to get length -; store length into IOCB - lda loadaddr - sta ICBAL+$10 - lda loadaddr+1 - sta ICBAH+$10 - - sec - lda tmp - sbc loadaddr - sta ICBLL+$10 - lda tmp+1 - sbc loadaddr+1 - sta ICBLH+$10 - inc ICBLL+$10 - bne noinc - inc ICBLH+$10 -noinc: - jsr read_segment - bmi fail - -; if INITAD modified, JSR there - lda INITAD - ora INITAD+1 - beq readheader - - jsr do_init - - lda #0 - sta INITAD - sta INITAD+1 - beq readheader ; branch always - -do_init - jmp (INITAD) - -close_file: - jsr fclose - -; JSR through RUNAD if it's not zero - lda RUNAD - ora RUNAD+1 - beq norun - - jsr do_run - jmp (DOSVEC) ; does not return - -; If there was no run address, we were probably loading an R: driver, so -; our caller is safe to return to -norun - lda #0 ; return 0 - tax - rts - -read2bytes: - lda #tmp - sta ICBAL+$10 - lda #2 - sta ICBLL+$10 - lda #0 - sta ICBAH+$10 - sta ICBLH+$10 -read_segment: - lda #C_GETCHR - sta ICCOM+$10 - ldx #$10 - jmp CIOV - -do_run - jmp (RUNAD) - -fclose - lda #C_CLOSE - sta ICCOM+$10 - ldx #$10 - jmp CIOV - -endmain - -; word RUNAD -; word RUNAD+1 -; word main diff --git a/src/aexec.s b/src/aexec.s new file mode 100644 index 0000000..27e8909 --- /dev/null +++ b/src/aexec.s @@ -0,0 +1,202 @@ + +; Load an Atari DOS executable, including support for init and run vectors +; Parameters: nul-terminated filename pointer in A/X (lo/hi) +; Return value: 0 for success, nonzero on error, never returns if exe has +; a run address. + +; This is for the Atari, but it gets built with "-t none" to +; avoid ld65 adding the C runtime startup code. Also, there is +; NO run address in this file. + +; "Link" to your program with "cat aexec.xex yourprog.xex > newprog.xex" + +; int __fastcall__ (*atari_exec_p)(char *) = (int __fastcall__ (*)(char *))0x600; +; #define atari_exec(x) ((*atari_exec_p)(x)) +; then call with: atari_exec("D:PROGRAM.XEX"); + +; If the file can't be opened for whatever reason, atari_exec() returns a +; nonzero result (the Atari error number). + +; If the file loads OK and has a run address, atari_exec() never returns +; (runs the loaded program, then exits to DOS if/when the program exits). +; This means there's no memory conflict between caller and callee. + +; If there was no run address, atari_exec returns 0 to the caller. +; The caller is responsible for making sure the loaded program doesn't +; step on the memory used by the caller or atari_exec itself! + +; If the file is openable but invalid (not a XEX, or truncated), current +; atari_exec() implementation hangs the machine with a red screen, since +; there's no way to know whether the partially-loaded program overwrote +; the caller... + + + .include "atari.inc" + +tmp = $d4 ; aka FR0 +loadaddr = $d6 + +main = $0600 + + .org main-6 + .word $FFFF + .word main + .word endmain-1 + + .org main + pha + txa + pha + jsr fclose + pla + tax + pla + + sta ICBAL+16 + stx ICBAH+16 + sta tmp + stx tmp+1 + ldy #0 + +; do an OPEN #1,4,0,$filename + +; get length of filename +fnameloop: + lda (tmp),y + beq fndone + iny + bne fnameloop + + ; set IOCB #1 buffer addr, buffer len, etc +fndone: + sty ICBLL+$10 + lda #0 + sta ICBLH+$10 + sta ICAX2+$10 + + ; init these to 0 so we can tell if they change + sta RUNAD + sta RUNAD+1 + sta INITAD + sta INITAD+1 + + ldx #4 + stx ICAX1+$10 + dex + stx ICCOM+$10 ; cmd #3 = OPEN + + ldx #$10 + jsr CIOV ; do the OPEN + bpl readheader + + tya ; CIO returns error code in Y reg + ldx #0 + rts + +fail: + lda #$48 + sta 710 +hang: bne hang + +readheader: +; read 2 bytes into local buffer + jsr read2bytes + bpl ok + cpy #136 ; EOF + bne fail + beq close_file ; if at EOF, close the file + +; if they're $ffff, try again +ok: + lda tmp + tax + and tmp+1 + cmp #$ff + beq readheader + +; store those 2 bytes in loadaddr + lda tmp+1 + sta loadaddr+1 + stx loadaddr + +; read 2 more bytes into local buffer (end addr) + jsr read2bytes + bmi fail +; subtract loadaddr from end addr, add 1, to get length +; store length into IOCB + lda loadaddr + sta ICBAL+$10 + lda loadaddr+1 + sta ICBAH+$10 + + sec + lda tmp + sbc loadaddr + sta ICBLL+$10 + lda tmp+1 + sbc loadaddr+1 + sta ICBLH+$10 + inc ICBLL+$10 + bne noinc + inc ICBLH+$10 +noinc: + jsr read_segment + bmi fail + +; if INITAD modified, JSR there + lda INITAD + ora INITAD+1 + beq readheader + + jsr do_init + + lda #0 + sta INITAD + sta INITAD+1 + beq readheader ; branch always + +do_init: + jmp (INITAD) + +close_file: + jsr fclose + +; JSR through RUNAD if it's not zero + lda RUNAD + ora RUNAD+1 + beq norun + + jsr do_run + jmp (DOSVEC) ; does not return + +; If there was no run address, we were probably loading an R: driver, so +; our caller is safe to return to +norun: + lda #0 ; return 0 + tax + rts + +read2bytes: + lda #tmp + sta ICBAL+$10 + lda #2 + sta ICBLL+$10 + lda #0 + sta ICBAH+$10 + sta ICBLH+$10 +read_segment: + lda #GETCHR + sta ICCOM+$10 + ldx #$10 + jmp CIOV + +do_run: + jmp (RUNAD) + +fclose: + lda #CLOSE + sta ICCOM+$10 + ldx #$10 + jmp CIOV + +endmain: diff --git a/src/loadxex.s b/src/loadxex.s index 7008f75..bf0f3c6 100644 --- a/src/loadxex.s +++ b/src/loadxex.s @@ -5,7 +5,8 @@ ; I'd have to make AUTORUN.SYS a copy of FUJIMENU.COM with ; the serial driver prepended. -RUNAD = $02e0 + .include "atari.inc" + atari_exec = $0600 main = $2e00 ; same place as cc65 -- cgit v1.2.3