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:
Dave Lyons 2020-08-29 22:01:28 -07:00
parent 09c28e218f
commit 006c164cb5
5 changed files with 273 additions and 80 deletions

View File

@ -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>

View File

@ -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

View File

@ -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)(); }

View File

@ -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
View 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
}