From 172ce143498cd810816e12d19f835ecf2d309ec5 Mon Sep 17 00:00:00 2001 From: Greg King Date: Sun, 25 Aug 2013 00:31:36 -0400 Subject: [PATCH 1/5] Made an exec() program-chaining function for the Commodore libraries. --- libsrc/cbm/exec.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 libsrc/cbm/exec.c diff --git a/libsrc/cbm/exec.c b/libsrc/cbm/exec.c new file mode 100644 index 000000000..302115c17 --- /dev/null +++ b/libsrc/cbm/exec.c @@ -0,0 +1,99 @@ +/* +** Program-chaining function for Commodore platforms. +** +** 2013-08-24, Greg King +** +** This function exploits the program-chaining feature in CBM BASIC's ROM. +** It puts the desired program's name and unit number into a LOAD statement. +** Then, it points BASIC to that statement, so that the ROM will run that +** statement after this program quits. The ROM will load the next program, +** and execute it. +*/ + +#include +#include +#include +#include +#include +#include +#if defined(__CBM610__) +# include +#elif defined(__CBM510__) +# include +#endif + + +#pragma data-name(push, "LOWCODE") +static struct line { + const char end_of_line; + const struct line *const next; + const unsigned line_num; + const char load_token, quotes[2], add_token, quote; + char name[21]; + const char comma; + char unit[3]; +} basic = { + '\0', &basic + 1, /* high byte must be non-zero */ + 0, 0x93, + + /* This string operation copies the name to high BASIC RAM. + ** So, it won't be overwritten when the next program is loaded. + */ + "\"\"", 0xaa, '\"', + "\" ", /* format: "123:1234567890123456\"" */ + ',', "01" +}; +#pragma data-name(pop) + +/* These values are platform-specific. */ +extern const struct line *txtptr; +#pragma zpsym("txtptr") +extern char basbuf[]; /* BASIC's input buffer */ +extern void basbuf_len[]; +#pragma zpsym("basbuf_len") + + +int __fastcall__ exec (const char* progname, const char* cmdline) +{ + static int fd; + static unsigned char dv, n = 0; + + /* Exclude devices that can't load files. */ + dv = getcurrentdevice (); + if (dv < 8 && dv != 1 || dv > 30) { + return _mappederrno (9); /* illegal device number */ + } + utoa (dv, basic.unit, 10); + + /* Don't try to run a program that can't be found. */ + fd = open (progname, O_RDONLY); + if (fd < 0) { + return fd; + } + close (fd); + + do { + if ((basic.name[n] = progname[n]) == '\0') { + break; + } + } while (++n < 20); /* truncate long names */ + basic.name[n] = '\"'; + + /* Build the next program's argument list. */ + basbuf[0] = 0x8f; /* REM token */ + basbuf[1] = '\0'; + if (cmdline != NULL) { + strncat (basbuf, cmdline, (size_t)basbuf_len - 2); + } + +#if defined(__CBM510__) || defined(__CBM610__) + pokewsys ((unsigned)&txtptr, (unsigned)&basic); +#else + txtptr = &basic; +#endif + + /* (The return code, in ST, will be destroyed by LOAD. + ** So, don't bother to set it here.) + */ + exit (__AX__); +} From d0fb1fe0ae489c23ff753011575331be05fb25a3 Mon Sep 17 00:00:00 2001 From: Greg King Date: Sun, 25 Aug 2013 00:43:23 -0400 Subject: [PATCH 2/5] Added the model-specific addresses that the CBM exec() needs. --- asminc/c128.inc | 1 + asminc/c64.inc | 1 + asminc/cbm510.inc | 20 ++++++++++++++------ asminc/cbm610.inc | 14 ++++++++++---- asminc/pet.inc | 4 ++++ asminc/plus4.inc | 1 + asminc/vic20.inc | 1 + libsrc/cbm/execvars.s | 28 ++++++++++++++++++++++++++++ libsrc/pet/mainargs.s | 1 - 9 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 libsrc/cbm/execvars.s diff --git a/asminc/c128.inc b/asminc/c128.inc index 1fb8b397c..aac8678bf 100644 --- a/asminc/c128.inc +++ b/asminc/c128.inc @@ -6,6 +6,7 @@ ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff +TXTPTR := $3D ; Pointer into BASIC source code TIME := $A0 ; 60HZ clock FNAM_LEN := $B7 ; Length of filename SECADR := $B9 ; Secondary address diff --git a/asminc/c64.inc b/asminc/c64.inc index f5dbcf549..f450fcc0b 100644 --- a/asminc/c64.inc +++ b/asminc/c64.inc @@ -6,6 +6,7 @@ ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff +TXTPTR := $7A ; Pointer into BASIC source code TIME := $A0 ; 60 HZ clock FNAM_LEN := $B7 ; Length of filename SECADR := $B9 ; Secondary address diff --git a/asminc/cbm510.inc b/asminc/cbm510.inc index 827c507fc..f031a1e35 100644 --- a/asminc/cbm510.inc +++ b/asminc/cbm510.inc @@ -3,7 +3,8 @@ ; ; Taken from a kernal disassembly done by myself in 2000/2001. ; -; Ullrich von Bassewitz, 13.09.2001 +; 2001-09-13, Ullrich von Bassewitz +; 2013-08-23, Greg King ;----------------------------------------------------------------------------- @@ -12,6 +13,8 @@ ExecReg = $00 IndReg = $01 +TXTPTR := $85 ; Far pointer into BASIC source code + ; --------------------------------------------------------------------------- ; Screen size @@ -21,7 +24,7 @@ YSIZE = 25 ;----------------------------------------------------------------------------- ; I/O Definitions -; I/O $d800: VIC +; I/O $d800: VIC-II VIC_SPR0_X = $00 VIC_SPR0_Y = $01 @@ -75,7 +78,6 @@ VIC_BG_COLOR2 = $23 VIC_BG_COLOR3 = $24 - ; I/O $da00: SID 6581 SID_S1Lo = $00 @@ -112,7 +114,7 @@ SID_Noise = $1B SID_Read3 = $1C -; I/O $db00: CIA 6526 Inter Process Communication +; I/O $db00: CIA 6526, Inter Process Communication ; I/O $dc00: CIA 6526 .struct CIA @@ -176,7 +178,13 @@ SID_Read3 = $1C .endstruct -; Out video memory address +;----------------------------------------------------------------------------- +; Our video memory address -COLOR_RAM = $D400 ; System bank +COLOR_RAM := $D400 ; System bank + +;----------------------------------------------------------------------------- + +BASIC_BUF := $FB5E ; Bank 0 location of command-line +BASIC_BUF_LEN = 162 ; Maximum length of command-line diff --git a/asminc/cbm610.inc b/asminc/cbm610.inc index 94256eeb1..10d194ea7 100644 --- a/asminc/cbm610.inc +++ b/asminc/cbm610.inc @@ -9,8 +9,10 @@ ; --------------------------------------------------------------------------- ; Zeropage stuff -ExecReg = $00 -IndReg = $01 +ExecReg := $00 +IndReg := $01 + +TXTPTR := $85 ; Far pointer into BASIC source code ; --------------------------------------------------------------------------- ; Screen size @@ -29,7 +31,8 @@ YSIZE = 25 DATA .byte .endstruct -; I/O $db00: CIA 6526 Inter Process Communication + +; I/O $db00: CIA 6526, Inter Process Communication ; ; IPCcia = $db00 @@ -68,7 +71,6 @@ YSIZE = 25 ; cia = $dc00 - ; I/O $dd00: ACIA 6551 ; ; acia = $dd00 @@ -108,3 +110,7 @@ YSIZE = 25 ; tpi2 = $df00 +;----------------------------------------------------------------------------- + +BASIC_BUF := $FA5E ; Bank 1 location of command-line +BASIC_BUF_LEN = 162 ; Maximum length of command-line diff --git a/asminc/pet.inc b/asminc/pet.inc index a3dadf48d..1ebf391f9 100644 --- a/asminc/pet.inc +++ b/asminc/pet.inc @@ -7,6 +7,7 @@ ; Zero page, Commodore stuff MEMSIZE := $34 ; Size of memory installed +TXTPTR := $77 ; Pointer into BASIC source code TIME := $8D ; 60HZ clock KEY_COUNT := $9E ; Number of keys in input buffer RVS := $9F ; Reverse flag @@ -24,6 +25,9 @@ SCR_LINELEN := $D5 ; Screen line length CURS_Y := $D8 ; Cursor row FNADR := $DA ; Pointer to file name +BASIC_BUF := $200 ; Location of command-line +BASIC_BUF_LEN = 81 ; Maximum length of command-line + KEY_BUF := $26F ; Keyboard buffer ;---------------------------------------------------------------------------- diff --git a/asminc/plus4.inc b/asminc/plus4.inc index 014c18e60..17e250508 100644 --- a/asminc/plus4.inc +++ b/asminc/plus4.inc @@ -7,6 +7,7 @@ ; Zero page, Commodore stuff TMPPTR := $22 ; Temporary ptr used by BASIC +TXTPTR := $3B ; Pointer into BASIC source code TIME := $A3 ; 60HZ clock FNAM_LEN := $AB ; Length of filename LFN := $AC ; Logical file number diff --git a/asminc/vic20.inc b/asminc/vic20.inc index 6780d067d..c42db4258 100644 --- a/asminc/vic20.inc +++ b/asminc/vic20.inc @@ -6,6 +6,7 @@ ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff +TXTPTR := $7A ; Pointer into BASIC source code TIME := $A0 ; 60HZ clock FNAM_LEN := $B7 ; Length of filename SECADR := $B9 ; Secondary address diff --git a/libsrc/cbm/execvars.s b/libsrc/cbm/execvars.s new file mode 100644 index 000000000..02eabc12e --- /dev/null +++ b/libsrc/cbm/execvars.s @@ -0,0 +1,28 @@ +; +; Platform-specific variables for the exec program-chaining function +; + +.if .defined (__C128__) + .include "c128.inc" +.elseif .defined (__C16__) + .include "c16.inc" +.elseif .defined (__C64__) + .include "c64.inc" +.elseif .defined (__CBM510__) + .include "cbm510.inc" +.elseif .defined (__CBM610__) + .include "cbm610.inc" +.elseif .defined (__PET__) + .include "pet.inc" +.elseif .defined (__PLUS4__) + .include "plus4.inc" +.else + .include "vic20.inc" +.endif + + .export _txtptr:zp, _basbuf, _basbuf_len:zp + +_txtptr := TXTPTR + +_basbuf := BASIC_BUF +_basbuf_len = BASIC_BUF_LEN diff --git a/libsrc/pet/mainargs.s b/libsrc/pet/mainargs.s index 9a63f50c2..0d5b18987 100644 --- a/libsrc/pet/mainargs.s +++ b/libsrc/pet/mainargs.s @@ -13,7 +13,6 @@ MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code NAME_LEN = 16 ; maximum length of command-name -BASIC_BUF= $200 ;--------------------------------------------------------------------------- From 2d66c27462c45845e710cd2f21eff643fe7617bb Mon Sep 17 00:00:00 2001 From: Greg King Date: Sun, 25 Aug 2013 00:49:03 -0400 Subject: [PATCH 3/5] Added test programs for the exec() function. --- testcode/lib/arg-test.c | 3 +++ testcode/lib/exec-test1.c | 24 ++++++++++++++++++++++++ testcode/lib/exec-test2.c | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 testcode/lib/exec-test1.c create mode 100644 testcode/lib/exec-test2.c diff --git a/testcode/lib/arg-test.c b/testcode/lib/arg-test.c index c752acaeb..5c28faec0 100644 --- a/testcode/lib/arg-test.c +++ b/testcode/lib/arg-test.c @@ -9,6 +9,9 @@ int main (int argc, char* argv[]) for (I = 0; I < argc; ++I) { printf ("argv[%2d]: \"%s\"\n", I, argv[I]); } + + printf ("\n"); + getchar (); return EXIT_SUCCESS; } diff --git a/testcode/lib/exec-test1.c b/testcode/lib/exec-test1.c new file mode 100644 index 000000000..e2548fb0a --- /dev/null +++ b/testcode/lib/exec-test1.c @@ -0,0 +1,24 @@ +/* +** These programs test CC65's exec() program-chaining function. +** exec-test1 runs exec-test2 -- that tests the loading and starting of another +** program. Then, exec-test2 runs arg-test -- that tests command-line argument +** passing. +** +** 2013-08-24, Greg King +*/ + +#include +#include +#include +#include + +int main (void) { + clrscr (); + cprintf ("\nExec-test #1 -- launching #2...\r\n"); + + exec ("exec-test2", ""); + + cprintf ("\nFailed to find #2:\r\n %s.\r\n", _stroserror (_oserror)); + cgetc (); + return _oserror; +} diff --git a/testcode/lib/exec-test2.c b/testcode/lib/exec-test2.c new file mode 100644 index 000000000..e6c844a8e --- /dev/null +++ b/testcode/lib/exec-test2.c @@ -0,0 +1,23 @@ +/* +** These programs test CC65's exec() program-chaining function. +** exec-test1 runs exec-test2 -- that tests the loading and starting of another +** program. Then, exec-test2 runs arg-test -- that tests command-line argument +** passing. +** +** 2013-08-24, Greg King +*/ + +#include +#include +#include +#include + +int main (void) { + cprintf ("\nExec-test #2 -- launching arg-test...\r\n\n"); + + exec ("arg-test", "arg1 arg2 \"\" arg4"); + + cprintf ("\nFailed to find arg-test:\r\n %s.\r\n", _stroserror (_oserror)); + cgetc (); + return _oserror; +} From 6a9ab1a69a5906aef8448d4b0424485bf947bfba Mon Sep 17 00:00:00 2001 From: Greg King Date: Sun, 25 Aug 2013 00:58:27 -0400 Subject: [PATCH 4/5] Added a little more info about how CBM program-chaining works. --- libsrc/cbm/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/cbm/exec.c b/libsrc/cbm/exec.c index 302115c17..dec2e0080 100644 --- a/libsrc/cbm/exec.c +++ b/libsrc/cbm/exec.c @@ -7,7 +7,7 @@ ** It puts the desired program's name and unit number into a LOAD statement. ** Then, it points BASIC to that statement, so that the ROM will run that ** statement after this program quits. The ROM will load the next program, -** and execute it. +** and will execute it (because the LOAD will be seen in a running program). */ #include From 67571d4f5f79369409c472904c066d3d41389040 Mon Sep 17 00:00:00 2001 From: Greg King Date: Mon, 26 Aug 2013 22:02:00 -0400 Subject: [PATCH 5/5] Changed some CPU memory-mapped register definitions from expression mode into label mode. --- asminc/cbm510.inc | 6 +++--- asminc/cbm610.inc | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/asminc/cbm510.inc b/asminc/cbm510.inc index f031a1e35..dfeee1d4e 100644 --- a/asminc/cbm510.inc +++ b/asminc/cbm510.inc @@ -4,14 +4,14 @@ ; Taken from a kernal disassembly done by myself in 2000/2001. ; ; 2001-09-13, Ullrich von Bassewitz -; 2013-08-23, Greg King +; 2013-08-26, Greg King ;----------------------------------------------------------------------------- ; Zeropage stuff -ExecReg = $00 -IndReg = $01 +ExecReg := $00 ; Controls execution memory bank +IndReg := $01 ; Controls indirect indexed load-store bank TXTPTR := $85 ; Far pointer into BASIC source code diff --git a/asminc/cbm610.inc b/asminc/cbm610.inc index 10d194ea7..f442f5da8 100644 --- a/asminc/cbm610.inc +++ b/asminc/cbm610.inc @@ -1,16 +1,17 @@ ; -; Zeropage and I/O definitions for the CBM 610 +; Zero page variables and I/O definitions for the CBM 610 ; ; Taken from a kernal disassembly done by myself in 1987. ; -; Ullrich von Bassewitz, 28.09.1998 +; 1998-09-28, Ullrich von Bassewitz +; 2013-08-26, Greg King ; --------------------------------------------------------------------------- ; Zeropage stuff -ExecReg := $00 -IndReg := $01 +ExecReg := $00 ; Controls execution memory bank +IndReg := $01 ; Controls indirect indexed load-store bank TXTPTR := $85 ; Far pointer into BASIC source code