mirror of
https://github.com/david-schmidt/Davex.git
synced 2026-01-23 16:15:57 +00:00
Work in progress on hexdump command (in C) and support for calling Davex routines and ProDOS from C.
This commit is contained in:
@@ -889,7 +889,7 @@ pv_yesno:
|
||||
@yn: pha
|
||||
jsr calc_pindex
|
||||
pla
|
||||
sta parms+3,x
|
||||
sta parms+3,x ; retrieved result will be in A
|
||||
jmp chrget
|
||||
|
||||
;
|
||||
@@ -1269,7 +1269,7 @@ pv_devnum:
|
||||
pha
|
||||
jsr calc_pindex
|
||||
pla
|
||||
sta parms+3,x
|
||||
sta parms+3,x ; retrieved result will be in A
|
||||
jmp chrget
|
||||
dvnerr: lda #der_baddev
|
||||
jmp ProDOS_err
|
||||
|
||||
@@ -25,12 +25,22 @@ _XC_STARTUP:
|
||||
.export COUT
|
||||
COUT = $fded
|
||||
|
||||
.export _PRBYTE
|
||||
_PRBYTE = $fdda
|
||||
|
||||
; export COUT() for direct use from C: Prints character in inverse if bit 7 is clear.
|
||||
.export _COUT
|
||||
_COUT = $fded
|
||||
_COUT = cout
|
||||
|
||||
.export _CROUT
|
||||
_CROUT = crout
|
||||
|
||||
.export _PRBYTE
|
||||
_PRBYTE = prbyte
|
||||
|
||||
.export _SETNORM
|
||||
_SETNORM = normal
|
||||
|
||||
.export _SETINV
|
||||
_SETINV = inverse
|
||||
|
||||
|
||||
; __fastcall__ calling convention: last parameter is in sreg+1/sreg/X/A
|
||||
; return value in XA, or sreg+1/sreg/X/A
|
||||
@@ -41,11 +51,37 @@ _xgetparm_ch_nil:
|
||||
jsr xgetparm_ch
|
||||
jmp returnTrueForCLC
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_byte(uint8_t optionCharacter, uint8_t* outValue); // int1, filetype, devnum, yesno
|
||||
; [TODO]
|
||||
; extern _Bool __fastcall__ xgetparm_ch_int1(uint8_t optionCharacter, uint8_t* outValue); // int1
|
||||
.export _xgetparm_ch_int1
|
||||
_xgetparm_ch_int1:
|
||||
stx p+1
|
||||
sta p
|
||||
jsr popa ; option character [TODO] pop just 1 byte, or 2?
|
||||
jsr xgetparm_ch ; 1-byte result in Y
|
||||
bcs :+
|
||||
tya
|
||||
ldy #0
|
||||
sta (p),y
|
||||
: jmp returnTrueForCLC
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_int2(uint8_t optionCharacter, uint16_t* outValue);
|
||||
; [TODO]
|
||||
.export _xgetparm_ch_int2
|
||||
_xgetparm_ch_int2:
|
||||
stx num+1
|
||||
sta num
|
||||
jsr popa ; option character [TODO] pop just 1 byte, or 2?
|
||||
jsr xgetparm_ch ; 2-byte result in XY
|
||||
getparm_return_int2:
|
||||
bcs :+
|
||||
; Result is in XY, and we need to store it at (num) as 2 bytes
|
||||
tya
|
||||
ldy #0
|
||||
sta (num),y
|
||||
txa
|
||||
iny
|
||||
sta (num),y
|
||||
: jmp returnTrueForCLC
|
||||
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_int3(uint8_t optionCharacter, uint32_t* outValue);
|
||||
.export _xgetparm_ch_int3
|
||||
@@ -72,6 +108,20 @@ getparm_return_int3:
|
||||
sta (num),y
|
||||
: jmp returnTrueForCLC
|
||||
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_ch_byte(uint8_t optionCharacter, uint8_t* outValue); // filetype, devnum, yesno
|
||||
.export _xgetparm_ch_byte
|
||||
_xgetparm_ch_byte:
|
||||
stx p+1
|
||||
sta p
|
||||
jsr popa ; option character [TODO] pop just 1 byte, or 2?
|
||||
jsr xgetparm_ch ; 1-byte result in A (differs from int1)
|
||||
bcs :+
|
||||
ldy #0
|
||||
sta (p),y
|
||||
: jmp returnTrueForCLC
|
||||
|
||||
|
||||
; extern _Bool __fastcall__ xgetparm_n_int3(uint8_t index, uint32_t* outValue);
|
||||
.export _xgetparm_n_int3
|
||||
_xgetparm_n_int3:
|
||||
@@ -111,6 +161,7 @@ _xgetparm_n_int3:
|
||||
; extern void __fastcall__ xmessage(const uint8_t*);
|
||||
.export _xmessage
|
||||
_xmessage:
|
||||
; [TODO] export this from the shell as xmessage ?
|
||||
stx loadCharacter+2
|
||||
sta loadCharacter+1
|
||||
ldy #0
|
||||
@@ -326,5 +377,18 @@ _xgetnump:
|
||||
ldx #0 ;extend result to 16 bits
|
||||
rts
|
||||
|
||||
; extern uint8_t __fastcall__ ProDOS(uint8_t call, void* params);
|
||||
.export _ProDOS
|
||||
_ProDOS:
|
||||
stx @params+1
|
||||
sta @params
|
||||
jsr popa
|
||||
sta @callNum
|
||||
jsr mli
|
||||
@callNum: .byte 0
|
||||
@params: .addr 0
|
||||
ldx #0 ; error in A
|
||||
rts
|
||||
|
||||
.segment "ONCE"
|
||||
.segment "INIT"
|
||||
|
||||
@@ -44,23 +44,27 @@ struct XCHeader
|
||||
|
||||
extern void PRBYTE(uint8_t);
|
||||
extern void COUT(uint8_t);
|
||||
// [TODO] CROUT directly from ROM
|
||||
extern void CROUT();
|
||||
extern void SETNORM();
|
||||
extern void SETINV();
|
||||
|
||||
// #define FUNC(addr) ((void __fastcall__ (*)())addr)
|
||||
// void __fastcall__ xpoll_io() { FUNC(0xB05B)(); }
|
||||
|
||||
|
||||
// [TODO] _Bool -> bool ?
|
||||
extern _Bool __fastcall__ xgetparm_ch_nil(uint8_t optionCharacter);
|
||||
extern _Bool __fastcall__ xgetparm_ch_byte(uint8_t optionCharacter, uint8_t* outValue); // int1, filetype, devnum, yesno
|
||||
extern _Bool __fastcall__ xgetparm_ch_int1(uint8_t optionCharacter, uint8_t* outValue); // not for filetype, devnum, or yesno
|
||||
extern _Bool __fastcall__ xgetparm_ch_int2(uint8_t optionCharacter, uint16_t* outValue);
|
||||
extern _Bool __fastcall__ xgetparm_ch_int3(uint8_t optionCharacter, uint32_t* outValue);
|
||||
extern _Bool __fastcall__ xgetparm_ch_byte(uint8_t optionCharacter, uint8_t* outValue); // filetype, devnum, yesno
|
||||
extern _Bool __fastcall__ xgetparm_ch_string(uint8_t optionCharacter, uint8_t** outString);
|
||||
extern _Bool __fastcall__ xgetparm_ch_path(uint8_t optionCharacter, uint8_t** outPath);
|
||||
extern _Bool __fastcall__ xgetparm_ch_path_and_filetype(uint8_t optionCharacter, uint8_t** outPath, uint8_t* outFiletype);
|
||||
|
||||
extern _Bool __fastcall__ xgetparm_n_byte(uint8_t index, uint8_t* outValue); // int1, filetype, devnum, yesno
|
||||
extern _Bool __fastcall__ xgetparm_n_int1(uint8_t index, uint8_t* outValue); // not for filetype, devnum, or 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_byte(uint8_t index, uint8_t* outValue); // filetype, devnum, yesno
|
||||
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);
|
||||
@@ -106,7 +110,7 @@ extern uint8_t __fastcall__ xrdkey(); // ;v1.1
|
||||
extern void __fastcall__ xdirty(); // v1.1
|
||||
extern uint8_t __fastcall__ xgetnump(); // v1.1
|
||||
|
||||
// [TODO] extern void __fastcall__ xshell_info(unsigned char selector); // v1.25 // [TODO] Return value varies?
|
||||
// [TODO] extern void __fastcall__ xshell_info(uint8_t selector); // v1.25 // [TODO] Return value varies?
|
||||
// input: X=request code
|
||||
// output: CLC, requested information in registers/etc.
|
||||
// SEC, requested information not available
|
||||
@@ -117,10 +121,29 @@ extern uint8_t __fastcall__ xgetnump(); // v1.1
|
||||
// X=2: Get history buffer (AY=address, X=size in pages)
|
||||
// X=3: Get internal filetype table (AY=address)
|
||||
// X=4: Get internal filetype name table (AY=address)
|
||||
//
|
||||
// extern uint16_t __fastcall__ xshell_info_version(); -- returns $0abc ($0123 = 1.23)
|
||||
// extern uint8_t* __fastcall__ xshell_info_aliases(uint8_t* outPages);
|
||||
// extern uint8_t* __fastcall__ xshell_info_history(uint8_t* outPages);
|
||||
// extern uint8_t* __fastcall__ xshell_info_filetypes();
|
||||
// extern uint8_t* __fastcall__ xshell_info_filetype_names();
|
||||
|
||||
//
|
||||
|
||||
// [TODO] External commands may use 'filebuff', 'filebuff2', and 'filebuff3', defined in GLOBALS; each one is $400 bytes long.
|
||||
#define filebuff ((uint8_t*)0x800) // size $400
|
||||
#define filebuff2 ((uint8_t*)0xC00) // size $400
|
||||
#define filebuff3 ((uint8_t*)0x1000) // size $400
|
||||
|
||||
#define pagebuff ((uint8_t*)0x1800) // size $100
|
||||
#define catbuff ((uint8_t*)0x1A02) // size $80
|
||||
|
||||
#define wildstring1 ((uint8_t*)0x1C3F) // size 128
|
||||
#define wildstring2 ((uint8_t*)0x1CBF) // size 128
|
||||
#define wildseg ((uint8_t*)0x1D3F) // size 16
|
||||
|
||||
// [TODO] The high bit of 'xspeech' is on when a speech synthesizer is being used.
|
||||
// [TODO] xnum and others
|
||||
|
||||
// ProDOS
|
||||
extern uint8_t __fastcall__ ProDOS(uint8_t call, void* params);
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ const char gDescription[] = "\x17This is the description";
|
||||
|
||||
const int kFive = 5;
|
||||
|
||||
void CROUT() { putchar('\r'); }
|
||||
void Space() { putchar(' '); }
|
||||
|
||||
void main()
|
||||
|
||||
@@ -7,7 +7,7 @@ const char gDescription[]; // forward declaration, since gCommandHeader must com
|
||||
#define kMinDavexVersion 0x14
|
||||
#define kMinDavexVersionMinor 0
|
||||
|
||||
#define PARM_COUNT 7 // define before including DavexXC.h
|
||||
#define PARM_COUNT 8 // define before including DavexXC.h
|
||||
#include "DavexXC.h"
|
||||
|
||||
const struct XCHeader gCommandHeader =
|
||||
@@ -24,6 +24,7 @@ const struct XCHeader gCommandHeader =
|
||||
// Parameters (PARM_COUNT of them)
|
||||
{
|
||||
{ 0, t_wildpath },
|
||||
{ 'd', t_devnum },
|
||||
{ 'a', t_nil }, // ASCII only
|
||||
{ 'h', t_nil }, // Hex only
|
||||
{ 'o', t_nil }, // no Offsets displayed
|
||||
@@ -36,22 +37,27 @@ const struct XCHeader gCommandHeader =
|
||||
|
||||
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;
|
||||
uint8_t gDevNum;
|
||||
uint8_t gBlockMode;
|
||||
|
||||
uint32_t gOffset;
|
||||
uint8_t gBytesPerLine;
|
||||
uint16_t gAmountRead;
|
||||
|
||||
_Bool gDumpMemory;
|
||||
bool gDumpMemory;
|
||||
bool gBlockValid;
|
||||
|
||||
uint16_t gCurrentBlock;
|
||||
|
||||
|
||||
#define pagebuff ((uint8_t*)0x800)
|
||||
#define err_eof 0x4C // ProDOS end of file error
|
||||
|
||||
uint8_t ReadSome();
|
||||
bool ShouldHighlight(uint8_t);
|
||||
|
||||
void main()
|
||||
{
|
||||
@@ -59,6 +65,8 @@ void main()
|
||||
_Bool showHex = xgetparm_ch_nil('h');
|
||||
_Bool showOffsets = !xgetparm_ch_nil('o');
|
||||
gDumpMemory = xgetparm_ch_nil('m');
|
||||
gBlockMode = xgetparm_ch_byte('d', &gDevNum);
|
||||
gBlockValid = false;
|
||||
|
||||
if (!showASCII && !showHex)
|
||||
showASCII = showHex = true;
|
||||
@@ -69,8 +77,8 @@ void main()
|
||||
gEndOffset = 0xFFFFFF;
|
||||
|
||||
{
|
||||
const uint8_t bytesPerLine = showHex ? 16 : 64;
|
||||
for (gOffset = gStartOffset; gOffset < gEndOffset; gOffset += bytesPerLine)
|
||||
gBytesPerLine = showHex ? 16 : 64;
|
||||
for (gOffset = gStartOffset; gOffset < gEndOffset; gOffset += gBytesPerLine)
|
||||
{
|
||||
uint8_t err = ReadSome();
|
||||
if (err == err_eof)
|
||||
@@ -78,25 +86,33 @@ void main()
|
||||
if (err != 0)
|
||||
xProDOS_err(err); // does not return
|
||||
|
||||
#if 0 // using printf() added 1,885 bytes
|
||||
if (showOffsets)
|
||||
printf("%06lX: ", offset);
|
||||
#else
|
||||
// "Block n"
|
||||
if (gBlockMode && (gOffset & 511) == 0)
|
||||
{
|
||||
xmessage("Block ");
|
||||
xprdec_2(gOffset / 512);
|
||||
CROUT();
|
||||
}
|
||||
|
||||
// Offset:
|
||||
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)
|
||||
for (i = 0; i < gBytesPerLine; ++i)
|
||||
{
|
||||
PRBYTE(pagebuff[i]);
|
||||
uint8_t ch = pagebuff[i];
|
||||
bool inverse = ShouldHighlight(ch);
|
||||
if (inverse)
|
||||
SETINV();
|
||||
PRBYTE(ch);
|
||||
SETNORM();
|
||||
Space();
|
||||
}
|
||||
}
|
||||
@@ -104,13 +120,18 @@ void main()
|
||||
if (showASCII)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < bytesPerLine; ++i)
|
||||
for (i = 0; i < gBytesPerLine; ++i)
|
||||
{
|
||||
uint8_t ch = pagebuff[i] | 0x80;
|
||||
if (ch > 0xA0)
|
||||
putchar(ch);
|
||||
uint8_t ch = pagebuff[i];
|
||||
bool inverse = ShouldHighlight(ch);
|
||||
uint8_t ch7 = ch | 0x80;
|
||||
if (inverse)
|
||||
SETINV();
|
||||
if (ch7 > 0xA0)
|
||||
COUT(ch7);
|
||||
else
|
||||
putchar('.');
|
||||
SETNORM();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +143,19 @@ void main()
|
||||
}
|
||||
|
||||
|
||||
bool ShouldHighlight(uint8_t ch)
|
||||
{
|
||||
// [TODO] parse command-line options to specify what data to highlight
|
||||
if (gDumpMemory)
|
||||
return ch >= 0x80;
|
||||
|
||||
if (gBlockMode)
|
||||
return ch == 0x4C;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint8_t ByteFromMemory(uint32_t addr)
|
||||
{
|
||||
const uint8_t bank = addr >> 16;
|
||||
@@ -144,12 +178,35 @@ uint8_t ByteFromMemory(uint32_t addr)
|
||||
return *(uint8_t*)addr;
|
||||
}
|
||||
|
||||
// Returns a ProDOS error code; [TODO] sets gAmountRead? so we can stop at the end of the file
|
||||
|
||||
uint8_t GetBlockIntoFileBuff(uint16_t block)
|
||||
{
|
||||
struct RWBlockParams { uint8_t count; uint8_t devnum; uint8_t* buffer; uint16_t block; };
|
||||
static struct RWBlockParams blockParams = { 3, 0 /* dev */, filebuff, 0 };
|
||||
|
||||
if (gBlockValid && block == gCurrentBlock)
|
||||
return 0;
|
||||
|
||||
#define READ_BLOCK 0x80
|
||||
blockParams.devnum = gDevNum;
|
||||
blockParams.block = block;
|
||||
{
|
||||
uint8_t err = ProDOS(READ_BLOCK, &blockParams);
|
||||
if (err == 0)
|
||||
{
|
||||
gBlockValid = true;
|
||||
gCurrentBlock = block;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a ProDOS error code. Sets gAmountRead so we can stop at the end of the file.
|
||||
uint8_t ReadSome()
|
||||
{
|
||||
if (gDumpMemory)
|
||||
{
|
||||
// Read from offset to offset+bytesPerLine-1
|
||||
// Read from gOffset to gOffset+gBytesPerLine-1
|
||||
uint8_t i;
|
||||
for (i = 0; i < gBytesPerLine; ++i)
|
||||
pagebuff[i] = ByteFromMemory(gOffset + i);
|
||||
@@ -157,6 +214,23 @@ uint8_t ReadSome()
|
||||
return 0; // noErr
|
||||
}
|
||||
|
||||
if (gBlockMode)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < gBytesPerLine; ++i)
|
||||
{
|
||||
uint32_t offset = gOffset + i;
|
||||
uint16_t withinBlock = offset & 511;
|
||||
uint8_t err = GetBlockIntoFileBuff(offset / 512);
|
||||
if (err)
|
||||
xProDOS_err(err);
|
||||
|
||||
pagebuff[i] = filebuff[withinBlock];
|
||||
}
|
||||
gAmountRead = gBytesPerLine;
|
||||
return 0;
|
||||
}
|
||||
|
||||
xProDOS_err(0xFF); // [TODO] files not supported yet
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user