mirror of
https://github.com/david-schmidt/Davex.git
synced 2024-06-26 04:29:29 +00:00
Refine the cc65 external command support.
Implement xgetparm_ch_int3(). Work in progress: "hexdump" command that can dump files or memory.
This commit is contained in:
parent
09c28e218f
commit
006c164cb5
|
@ -70,7 +70,11 @@
|
|||
<exec dir="${srcdir}" executable="${assemblerPath}/ca65"><arg line="-t none -I . -l ${srcdir}/xtn/2/x10.lst ${srcdir}/xtn/2/x10.asm -o ${obj2xtndir}/x10.o" /></exec>
|
||||
<exec dir="${srcdir}" executable="${assemblerPath}/ca65"><arg line="-t none -I . -l ${srcdir}/xtn/2/xc.lst ${srcdir}/xtn/2/xc.asm -o ${obj2xtndir}/xc.o" /></exec>
|
||||
<echo message="Compiling Davex externals..."/>
|
||||
<exec dir="${srcdir}" executable="${assemblerPath}/cl65"><arg line="-t apple2 -I . -Oi -C ${srcdir}/xtn/2-cc65/apple2-DavexXC.cfg --start-addr 0x9000 ${srcdir}/xtn/2-cc65/DavexXC.s ${srcdir}/xtn/2-cc65/cctest.c -o ${obj2xtndir}/cctest -Wa,-I,${srcdir}/common/2" /></exec>
|
||||
<exec dir="${srcdir}" executable="${assemblerPath}/ca65"><arg line="-t apple2 -I . -l ${srcdir}/xtn/2/DavexXC.lst ${srcdir}/xtn/2-cc65/DavexXC.asm -o ${obj2xtndir}/DavexXC.o" /></exec>
|
||||
<exec dir="${srcdir}" executable="${assemblerPath}/cc65"><arg line="-t apple2 -I . -Oi ${srcdir}/xtn/2-cc65/cctest.c -o ${obj2xtndir}/cctest.asm" /></exec>
|
||||
<exec dir="${srcdir}" executable="${assemblerPath}/ca65"><arg line="-t none -I . -l ${srcdir}/xtn/2/cctest.lst ${obj2xtndir}/cctest.asm -o ${obj2xtndir}/cctest.o" /></exec>
|
||||
<exec dir="${srcdir}" executable="${assemblerPath}/cc65"><arg line="-t apple2 -I . -Oi ${srcdir}/xtn/2-cc65/hexdump.c -o ${obj2xtndir}/hexdump.asm" /></exec>
|
||||
<exec dir="${srcdir}" executable="${assemblerPath}/ca65"><arg line="-t none -I . -l ${srcdir}/xtn/2/hexdump.lst ${obj2xtndir}/hexdump.asm -o ${obj2xtndir}/hexdump.o" /></exec>
|
||||
|
||||
<!-- Disassembled Batch -->
|
||||
<exec dir="${srcdir}" executable="${assemblerPath}/ca65"><arg line="-t none -I . -l ${srcdir}/xtn/2/aaf.lst ${srcdir}/xtn/2/aaf.asm -o ${obj2xtndir}/aaf.o" /></exec>
|
||||
|
@ -163,6 +167,11 @@
|
|||
<exec dir="${obj2xtndir}" executable="${assemblerPath}/ld65"><arg line="-o viewdhr -m viewdhr.map -C ${srcdir}/xtn/2/xtn_ac00.cfg viewdhr.o" /></exec>
|
||||
<exec dir="${obj2xtndir}" executable="${assemblerPath}/ld65"><arg line="-o viewhr -m viewhr.map -C ${srcdir}/xtn/2/xtn_ae00.cfg viewhr.o" /></exec>
|
||||
<exec dir="${obj2xtndir}" executable="${assemblerPath}/ld65"><arg line="-o wc -m wc.map -C ${srcdir}/xtn/2/xtn_a000.cfg wc.o" /></exec>
|
||||
|
||||
<echo message="Linking C externals..."/>
|
||||
<exec dir="${obj2xtndir}" executable="${assemblerPath}/ld65"><arg line="--start-addr 0xA000 -o cctest -m cctest.map -C ${srcdir}/xtn/2-cc65/apple2-DavexXC.cfg cctest.o DavexXC.o ${assemblerPath}/../lib/apple2.lib" /></exec>
|
||||
<exec dir="${obj2xtndir}" executable="${assemblerPath}/ld65"><arg line="--start-addr 0xA000 -o hexdump -m hexdump.map -C ${srcdir}/xtn/2-cc65/apple2-DavexXC.cfg hexdump.o DavexXC.o ${assemblerPath}/../lib/apple2.lib" /></exec>
|
||||
|
||||
</target>
|
||||
<target name="xtn-builddsk">
|
||||
<!--
|
||||
|
@ -240,6 +249,7 @@
|
|||
<appleCommander command="p" input="${obj2xtndir}/wc" imagename="${distdir}/DavexProDOS.po" filename="xtn/wc" type="p8c" address="32769"/>
|
||||
|
||||
<appleCommander command="p" input="${obj2xtndir}/cctest" imagename="${distdir}/DavexProDOS.po" filename="xtn/cctest" type="p8c" address="32769"/>
|
||||
<appleCommander command="p" input="${obj2xtndir}/hexdump" imagename="${distdir}/DavexProDOS.po" filename="xtn/hexdump" type="p8c" address="32769"/>
|
||||
|
||||
<echo message="ProDOS 3.5 disk externals complete."/>
|
||||
</target>
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
|
||||
; .include "Common/2/Globals2.asm" ; trying to use -Wa,-I,${srcdir}/... to make this work
|
||||
; .include "Common/2/Apple.Globals2.asm"
|
||||
; .include "Common/2/Mli.globals2.asm"
|
||||
; .include "Common/Macros.asm"
|
||||
.include "Common/2/Globals2.asm"
|
||||
.include "Common/2/Apple.Globals2.asm"
|
||||
.include "Common/2/Mli.globals2.asm"
|
||||
.include "Common/Macros.asm"
|
||||
|
||||
CSTACK = $B000 ; AF00..AFFF
|
||||
|
||||
.segment "STARTUP"
|
||||
__STARTUP__:
|
||||
_STARTUP:
|
||||
.export __STARTUP__
|
||||
.export _STARTUP
|
||||
_XC_STARTUP:
|
||||
.export _XC_STARTUP
|
||||
.import _main
|
||||
.importzp sp
|
||||
.importzp sreg
|
||||
.importzp num
|
||||
.import popa
|
||||
|
||||
lda #>CSTACK
|
||||
ldx #<CSTACK
|
||||
|
@ -23,68 +21,19 @@ _STARTUP:
|
|||
; [TODO] Call constructors/inits, and initialize any static data
|
||||
jmp _main
|
||||
|
||||
; Override the library COUT, which would enable language-card memory afterwards.
|
||||
.export COUT
|
||||
COUT = $fded
|
||||
; Override the library COUT, which would enable language-card memory afterwards. This is called by puts(), for example.
|
||||
.export COUT
|
||||
COUT = $fded
|
||||
|
||||
.export _PRBYTE
|
||||
_PRBYTE = $fdda
|
||||
|
||||
;-----
|
||||
|
||||
; [TODO] .h declarations for all these
|
||||
; [TODO] glue for the nontrivial ones
|
||||
.if 1 ; [TODO] get from include file instead
|
||||
|
||||
xspeech = $60 ; zero page, 1 byte
|
||||
xnum = $61 ; zero page, 4 bytes
|
||||
|
||||
xgetparm_ch = $b000
|
||||
xgetparm_n = $b003
|
||||
xmess = $b006
|
||||
xprint_ftype = $b009
|
||||
xprint_access = $b00c
|
||||
xprdec_2 = $b00f
|
||||
xprdec_3 = $b012
|
||||
xprdec_pad = $b015
|
||||
xprint_path = $b018
|
||||
xbuild_local = $b01b
|
||||
xprint_sd = $b01e
|
||||
xprint_drvr = $b021
|
||||
xredirect = $b024
|
||||
xpercent = $b027
|
||||
xyesno = $b02a
|
||||
xgetln = $b02d
|
||||
xbell = $b030
|
||||
xdowncase = $b033
|
||||
xplural = $b036
|
||||
xcheck_wait = $b039
|
||||
xpr_date_ay = $b03c
|
||||
xpr_time_ay = $b03f
|
||||
xProDOS_err = $b042
|
||||
xProDOS_er = $b045
|
||||
xerr = $b048
|
||||
xprdec_pady = $b04b
|
||||
xdir_setup = $b04e
|
||||
xdir_finish = $b051
|
||||
xread1dir = $b054
|
||||
xpmgr = $b057
|
||||
xmmgr = $b05a
|
||||
xpoll_io = $b05d
|
||||
xprint_ver = $b060
|
||||
xpush_level = $b063
|
||||
xfman_open = $b066
|
||||
xfman_read = $b069
|
||||
xrdkey = $b06c ;v1.1
|
||||
xdirty = $b06f ;v1.1
|
||||
xgetnump = $b072 ;v1.1
|
||||
xyesno2 = $b075 ;v1.2
|
||||
xdir_setup2 = $b078 ;v1.23
|
||||
xshell_info = $b07b ;v1.25
|
||||
.endif
|
||||
; export COUT() for direct use from C: Prints character in inverse if bit 7 is clear.
|
||||
.export _COUT
|
||||
_COUT = $fded
|
||||
|
||||
; __fastcall__ calling convention: last parameter is in sreg+1/sreg/X/A
|
||||
; return value in A, XA, sreg+1/sreg/X/A
|
||||
|
||||
|
||||
; return value in XA, or sreg+1/sreg/X/A
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_nil(uint8_t optionCharacter);
|
||||
.export _xgetparm_ch_nil
|
||||
|
@ -94,23 +43,88 @@ _xgetparm_ch_nil:
|
|||
jmp returnTrueForCLC
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_byte(uint8_t optionCharacter, uint8_t* outValue); // int1, filetype, devnum, yesno
|
||||
; [TODO]
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_int2(uint8_t optionCharacter, uint16_t* outValue);
|
||||
; [TODO]
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_int3(uint8_t optionCharacter, uint32_t* outValue);
|
||||
.export _xgetparm_ch_int3
|
||||
_xgetparm_ch_int3:
|
||||
stx num+1
|
||||
sta num
|
||||
jsr popa ; option character
|
||||
ora #$80 ; [TODO] change shell not to require high bit
|
||||
jsr xgetparm_ch
|
||||
getparm_return_int3:
|
||||
bcs :+
|
||||
; Result is in AXY, and we need to store it at (num) as 4 bytes
|
||||
pha
|
||||
tya
|
||||
ldy #0
|
||||
sta (num),y
|
||||
txa
|
||||
iny
|
||||
sta (num),y
|
||||
pla
|
||||
iny
|
||||
sta (num),y ; carry is still clear for no-error return
|
||||
lda #0
|
||||
iny
|
||||
sta (num),y
|
||||
: jmp returnTrueForCLC
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_n_int3(uint8_t index, uint32_t* outValue);
|
||||
.export _xgetparm_n_int3
|
||||
_xgetparm_n_int3:
|
||||
stx num+1
|
||||
sta num
|
||||
jsr popa ; option character
|
||||
ora #$80 ; [TODO] change shell not to require high bit
|
||||
jsr xgetparm_n
|
||||
jmp getparm_return_int3 ;[TODO] Better to turn this into a library, and just let this code be not-linked-in
|
||||
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_string(uint8_t optionCharacter, uint8_t** outString);
|
||||
; [TODO]
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_path(uint8_t optionCharacter, uint8_t** outPath);
|
||||
; [TODO]
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_path_and_filetype(uint8_t optionCharacter, uint8_t** outPath, uint8_t* outFiletype);
|
||||
; [TODO]
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_n_byte(uint8_t index, uint8_t* outValue); // int1, filetype, devnum, yesno
|
||||
; extern _Bool __fastcall__ xgetparm_n_int2(uint8_t index, uint16_t* outValue);
|
||||
; extern _Bool __fastcall__ xgetparm_n_int3(uint8_t index, uint32_t* outValue);
|
||||
; extern _Bool __fastcall__ xgetparm_n_string(uint8_t index, uint8_t** outString);
|
||||
; extern _Bool __fastcall__ xgetparm_n_path(uint8_t index, uint8_t** outPath);
|
||||
; extern _Bool __fastcall__ xgetparm_n_path_and_filetype(uint8_t index, uint8_t** outPath, uint8_t* outFiletype);
|
||||
; [TODO]
|
||||
|
||||
; extern void __fastcall__ xmessage(const uint8_t*); // calls puts() for now
|
||||
.import _puts
|
||||
; extern _Bool __fastcall__ xgetparm_n_int2(uint8_t index, uint16_t* outValue);
|
||||
; [TODO]
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_n_string(uint8_t index, uint8_t** outString);
|
||||
; [TODO]
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_n_path(uint8_t index, uint8_t** outPath);
|
||||
; [TODO]
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_n_path_and_filetype(uint8_t index, uint8_t** outPath, uint8_t* outFiletype);
|
||||
; [TODO]
|
||||
|
||||
|
||||
; extern void __fastcall__ xmessage(const uint8_t*);
|
||||
.export _xmessage
|
||||
_xmessage = _puts
|
||||
_xmessage:
|
||||
stx loadCharacter+2
|
||||
sta loadCharacter+1
|
||||
ldy #0
|
||||
loadCharacter: lda $7777,y ; operand modified
|
||||
beq :+
|
||||
ora #$80
|
||||
jsr cout
|
||||
iny
|
||||
bne loadCharacter
|
||||
inc loadCharacter+2
|
||||
bne loadCharacter
|
||||
: rts
|
||||
|
||||
; extern void __fastcall__ xprint_ftype(uint8_t); // print a filetype
|
||||
.export _xprint_ftype
|
|
@ -2,6 +2,8 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern void XC_STARTUP();
|
||||
|
||||
enum
|
||||
{
|
||||
t_nil = 0, // parameter with no associated value
|
||||
|
@ -18,6 +20,7 @@ enum
|
|||
|
||||
enum XCHardwareRequirements
|
||||
{
|
||||
kRequiresNothingSpecial = 0,
|
||||
kRequires40ColumnScreen = 0b10000000,
|
||||
kRequires80ColumnScreen = 0b01000000,
|
||||
kRequiresIIeOrIIgs = 0b00100000,
|
||||
|
@ -38,6 +41,11 @@ struct XCHeader
|
|||
uint8_t fParameters[PARM_COUNT+1][2]; // pairs of bytes, ending with 0,0
|
||||
};
|
||||
|
||||
|
||||
extern void PRBYTE(uint8_t);
|
||||
extern void COUT(uint8_t);
|
||||
// [TODO] CROUT directly from ROM
|
||||
|
||||
// #define FUNC(addr) ((void __fastcall__ (*)())addr)
|
||||
// void __fastcall__ xpoll_io() { FUNC(0xB05B)(); }
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
extern const char gDescription[];
|
||||
extern void STARTUP();
|
||||
extern const char gDescription[]; // forward declaration, because gCommandHeader must come firs
|
||||
|
||||
#define kMyVersion 0x10
|
||||
#define kMinDavexVersion 0x14
|
||||
|
@ -16,10 +15,10 @@ const struct XCHeader gCommandHeader =
|
|||
0x60, 0xEE, 0xEE,
|
||||
kMyVersion,
|
||||
kMinDavexVersion,
|
||||
0, // hardware requirements
|
||||
kRequiresNothingSpecial,
|
||||
gDescription,
|
||||
&gCommandHeader,
|
||||
STARTUP,
|
||||
XC_STARTUP,
|
||||
kMinDavexVersionMinor,
|
||||
0, 0, 0,
|
||||
// Parameters
|
||||
|
|
162
src/xtn/2-cc65/hexdump.c
Normal file
162
src/xtn/2-cc65/hexdump.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
const char gDescription[]; // forward declaration, since gCommandHeader must come first
|
||||
|
||||
#define kMyVersion 0x01
|
||||
#define kMinDavexVersion 0x14
|
||||
#define kMinDavexVersionMinor 0
|
||||
|
||||
#define PARM_COUNT 7 // define before including DavexXC.h
|
||||
#include "DavexXC.h"
|
||||
|
||||
const struct XCHeader gCommandHeader =
|
||||
{
|
||||
0x60, 0xEE, 0xEE,
|
||||
kMyVersion,
|
||||
kMinDavexVersion,
|
||||
kRequiresNothingSpecial,
|
||||
gDescription,
|
||||
&gCommandHeader,
|
||||
XC_STARTUP,
|
||||
kMinDavexVersionMinor,
|
||||
0, 0, 0,
|
||||
// Parameters
|
||||
{
|
||||
{ 0, t_wildpath },
|
||||
{ 0x80+'a', t_nil }, // ASCII only
|
||||
{ 0x80+'h', t_nil }, // Hex only
|
||||
{ 0x80+'o', t_nil }, // no Offsets displayed
|
||||
{ 0x80+'m', t_nil }, // dump Memory
|
||||
{ 0x80+'s', t_int3 }, // Starting offset
|
||||
{ 0x80+'e', t_int3 }, // Ending offset
|
||||
{ 0, 0 }
|
||||
}
|
||||
};
|
||||
|
||||
const char gDescription[] = "\x22" "Dump a file or memory in hex/ASCII";
|
||||
|
||||
void CROUT() { putchar('\r'); }
|
||||
void Space() { putchar(' '); }
|
||||
|
||||
uint32_t gStartOffset;
|
||||
uint32_t gEndOffset;
|
||||
|
||||
uint32_t gOffset;
|
||||
uint8_t gBytesPerLine;
|
||||
uint16_t gAmountRead;
|
||||
|
||||
_Bool gDumpMemory;
|
||||
|
||||
#define pagebuff ((uint8_t*)0x800)
|
||||
#define err_eof 0x4C // ProDOS end of file error
|
||||
|
||||
uint8_t ReadSome();
|
||||
|
||||
void main()
|
||||
{
|
||||
_Bool showASCII = xgetparm_ch_nil('a');
|
||||
_Bool showHex = xgetparm_ch_nil('h');
|
||||
_Bool showOffsets = !xgetparm_ch_nil('o');
|
||||
gDumpMemory = xgetparm_ch_nil('m');
|
||||
|
||||
if (!showASCII && !showHex)
|
||||
showASCII = showHex = true;
|
||||
|
||||
if (!xgetparm_ch_int3('s', &gStartOffset))
|
||||
gStartOffset = 0;
|
||||
if (!xgetparm_ch_int3('e', &gEndOffset))
|
||||
gEndOffset = 0xFFFFFF;
|
||||
|
||||
{
|
||||
const uint8_t bytesPerLine = showHex ? 16 : 64;
|
||||
for (gOffset = gStartOffset; gOffset < gEndOffset; gOffset += bytesPerLine)
|
||||
{
|
||||
uint8_t err = ReadSome();
|
||||
if (err == err_eof)
|
||||
break;
|
||||
if (err != 0)
|
||||
xProDOS_err(err); // does not return
|
||||
|
||||
#if 0 // using printf() added 1,885 bytes
|
||||
if (showOffsets)
|
||||
printf("%06lX: ", offset);
|
||||
#else
|
||||
PRBYTE(gOffset >> 16);
|
||||
if (gDumpMemory)
|
||||
putchar('/');
|
||||
PRBYTE(gOffset >> 8);
|
||||
PRBYTE(gOffset);
|
||||
// fputs(": ", stdout); // fputs() works, but it adds 80 bytes (in addition to puts() overhead)
|
||||
xmessage(": ");
|
||||
#endif
|
||||
|
||||
if (showHex)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < bytesPerLine; ++i)
|
||||
{
|
||||
PRBYTE(pagebuff[i]);
|
||||
Space();
|
||||
}
|
||||
}
|
||||
|
||||
if (showASCII)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < bytesPerLine; ++i)
|
||||
{
|
||||
uint8_t ch = pagebuff[i] | 0x80;
|
||||
if (ch > 0xA0)
|
||||
putchar(ch);
|
||||
else
|
||||
putchar('.');
|
||||
}
|
||||
}
|
||||
|
||||
CROUT();
|
||||
if (!xcheck_wait())
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t ByteFromMemory(uint32_t addr)
|
||||
{
|
||||
const uint8_t bank = addr >> 16;
|
||||
|
||||
// Not safe to read: $00C0xx, $01C0xx, $E0C0xx, $E1C0xx
|
||||
if ((bank & ~1) == 0 || (bank & ~1) == 0xE0)
|
||||
{
|
||||
const uint8_t page = addr >> 8;
|
||||
if (page == 0xC0)
|
||||
return 0x77;
|
||||
}
|
||||
|
||||
// [TODO] Language Card memory read (-L1, -L2)
|
||||
// [TODO] Auxmem memory read ($01xxxx)
|
||||
|
||||
// [TODO] Apple IIgs memory read
|
||||
if (bank > 0)
|
||||
return 0xEE;
|
||||
|
||||
return *(uint8_t*)addr;
|
||||
}
|
||||
|
||||
// Returns a ProDOS error code; [TODO] sets gAmountRead? so we can stop at the end of the file
|
||||
uint8_t ReadSome()
|
||||
{
|
||||
if (gDumpMemory)
|
||||
{
|
||||
// Read from offset to offset+bytesPerLine-1
|
||||
uint8_t i;
|
||||
for (i = 0; i < gBytesPerLine; ++i)
|
||||
pagebuff[i] = ByteFromMemory(gOffset + i);
|
||||
gAmountRead = gBytesPerLine;
|
||||
return 0; // noErr
|
||||
}
|
||||
|
||||
xProDOS_err(0xFF); // [TODO] files not supported yet
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user