SIO_WRITE = $50 ;write sector
SIO_READ = $52 ;read sector
SIO_STAT = $53 ;get status information
-SIO_VERIFY = $56 ;verify sector
+SIO_VERIFY = $56 ;verify sector
SIO_WRITEV = $57 ;write sector with verify
SIO_WRITETRK = $60 ;write track (Speedy)
SIO_READTRK = $62 ;read track (Speedy)
TIMER2 = $0310 ;2-byte final baud rate timer value
TEMP1 = $0312 ;TEMPORARY STORAGE REGISTER
;TEMP2 = $0314 ;##old## TEMPORARY STORAGE REGISTER
-TEMP2 = $0313 ;##1200xl## 1-byte temporary
+TEMP2 = $0313 ;##1200xl## 1-byte temporary
PTIMOT = $0314 ;##1200xl## 1-byte printer timeout
TEMP3 = $0315 ;TEMPORARY STORAGE REGISTER
SAVIO = $0316 ;SAVE SERIAL IN DATA PORT
;0=Cart Exists
CARTFG = $BFFD ;##rev2## 1-byte cartridge flags
;D7 0=Not a Diagnostic Cart
- ; 1=Is a Diagnostic cart and control is
+ ; 1=Is a Diagnostic cart and control is
; given to cart before any OS is init.
;D2 0=Init but Do not Start Cart
; 1=Init and Start Cart
DEGON = 6 ;INDICATES DEGREES
ASCZER = '0' ;ASCII ZERO
-COLON = $3A ;ASCII COLON
+COLON = $3A ;ASCII COLON
CR = $9B ;SYSTEM EOL (CARRIAGE RETURN)
;-------------------------------------------------------------------------
; VALUES for dos_type
;-------------------------------------------------------------------------
-ATARIDOS = 0
-SPARTADOS = 1
-OSADOS = 2 ; OS/A+
-MYDOS = 3
-XDOS = 4
+SPARTADOS = 0
+OSADOS = 1 ; OS/A+
+XDOS = 2
+ATARIDOS = 3
+MYDOS = 4
NODOS = 255
+; The DOSes with dos_type below or equal MAX_DOS_WITH_CMDLINE do support
+; command line arguments.
+MAX_DOS_WITH_CMDLINE = XDOS
+
+;-------------------------------------------------------------------------
+; XDOS defines (version 2.4, taken from xdos24.pdf)
+;-------------------------------------------------------------------------
+
+XOPT = $070B ; XDOS options
+XCAR = $070C ; XDOS cartridge address (+ $70D)
+XPAT = $086F ; XDOS bugfix and patch number
+XVER = $0870 ; XDOS version number
+XFILE = $087D ; XDOS filename buffer
+XLINE = $0880 ; XDOS DUP input line
+XGLIN = $0871 ; get line
+XSKIP = $0874 ; skip parameter
+XMOVE = $0877 ; move filename
+XGNUM = $087A ; get number
+XDEFDEV = $0816 ; current drive * undocumented *
;-------------------------------------------------------------------------
; End of atari.inc
CODE: load = MAIN, type = ro, define = yes;
RODATA: load = MAIN, type = ro, optional = yes;
DATA: load = MAIN, type = rw, optional = yes;
- BSS: load = MAIN, type = bss, define = yes;
+ BSS: load = MAIN, type = bss, define = yes, optional = yes;
INIT: load = MAIN, type = bss, optional = yes;
}
FEATURES {
<item>_getcolor
<item>_getdefdev
<item>_graphics
+<item>_is_cmdline_dos
<item>_rest_vecs
<item>_save_vecs
<item>_scroll
<!-- <item><ref id="_getcolor" name="_getcolor"> -->
<!-- <item><ref id="_getdefdev" name="_getdefdev"> -->
<!-- <item><ref id="_graphics" name="_graphics"> -->
+<item><ref id="_is_cmdline_dos" name="_is_cmdline_dos">
<!-- <item><ref id="_rest_vecs" name="_rest_vecs"> -->
<!-- <item><ref id="_save_vecs" name="_save_vecs"> -->
<!-- <item><ref id="_scroll" name="_scroll"> -->
</quote>
+<sect1>_is_cmdline_dos<label id="_is_cmdline_dos"><p>
+
+<quote>
+<descrip>
+<tag/Function/Determines whether the underlying DOS supports command line arguments.
+<tag/Header/<tt/<ref id="atari.h" name="atari.h">/
+<tag/Declaration/<tt/unsigned char _is_cmdline_dos (void);/
+<tag/Description/The function returns 0 if the DOS doesn't support command line arguments.
+It returns 1 if it does.
+<tag/Notes/<itemize>
+<item>Many Atari DOSes which don't support command line arguments immediately clear the screen
+and display their menu after a program exits. Therefore it might be difficult to read
+the last messages printed by the program prior to its exit. This function can be used
+to decide if a delay or wait for a key press should be executed when then program
+exits.
+</itemize>
+<tag/Availability/cc65 (<tt/atari/ and <tt/atarixl/ platforms)
+<tag/Example/<verb>
+/* Hello World for Atari */
+#include <stdio.h>
+#include <unistd.h>
+#include <atari.h>
+int main(void)
+{
+ printf("Hello World\n");
+ if (! _is_cmdline_dos())
+ sleep(5);
+ return 0;
+}
+</verb>
+</descrip>
+</quote>
+
+
<sect1>_poserror<label id="_poserror"><p>
<quote>
/* numlines < 0 scrolls down */
/* misc. functions */
-extern unsigned char get_ostype(void); /* get ROM version */
-extern unsigned char get_tv(void); /* get TV system */
-extern void _save_vecs(void); /* save system vectors */
-extern void _rest_vecs(void); /* restore system vectors */
-extern char *_getdefdev(void); /* get default floppy device */
+extern unsigned char get_ostype(void); /* get ROM version */
+extern unsigned char get_tv(void); /* get TV system */
+extern void _save_vecs(void); /* save system vectors */
+extern void _rest_vecs(void); /* restore system vectors */
+extern char *_getdefdev(void); /* get default floppy device */
+extern unsigned char _is_cmdline_dos(void); /* does DOS support command lines */
/* global variables */
extern unsigned char _dos_type; /* the DOS flavour */
#define AT_PAL 1
/* valid _dos_type values */
-#define ATARIDOS 0
-#define SPARTADOS 1
-#define OSADOS 2
-#define MYDOS 3
-#define XDOS 4
+#define SPARTADOS 0
+#define OSADOS 1
+#define XDOS 2
+#define ATARIDOS 3
+#define MYDOS 4
#define NODOS 255
/* Define hardware */
; Check for startup filename support
; ProDOS TechRefMan, chapter 5.1.5.1:
; "$2000 is a jump instruction. $2003 and $2004 are $EE."
-system: lda $2000
- cmp #$4C
+system: lda #$4C
+ cmp $2000
bne jump
- lda $2003
- cmp #$EE
+ lda #$EE
+ cmp $2003
bne jump
- lda $2004
- cmp #$EE
+ cmp $2004
bne jump
; Store cmdline in startup filename buffer
.data
-__dos_type: .byte 0 ; default to ATARIDOS
+__dos_type: .byte ATARIDOS; default to ATARIDOS
; startup code but is nevertheless included in the compiled program when
; needed.
+; XDOS support added 05/2016 by Christian Groessler
+
MAXARGS = 16 ; max. amount of arguments in arg. table
CL_SIZE = 64 ; command line buffer size
SPACE = 32 ; SPACE char.
.segment "ONCE"
+nargdos:rts
+
initmainargs:
lda __dos_type ; which DOS?
- cmp #ATARIDOS
- beq nargdos ; DOS does not support arguments
- cmp #MYDOS
- bne argdos ; DOS supports arguments
-nargdos:rts
+ cmp #MAX_DOS_WITH_CMDLINE + 1
+ bcs nargdos
; Initialize ourcl buffer
-argdos: lda #ATEOL
- sta ourcl+CL_SIZE
+argdos: ldy #ATEOL
+ sty ourcl+CL_SIZE
-; Move SpartaDOS command line to our own buffer
+; Move SpartaDOS/XDOS command line to our own buffer
+
+ cmp #XDOS
+ bne sparta
+
+ lda #<XLINE
+ sta ptr1
+ lda #>XLINE
+ sta ptr1+1
+ bne cpcl0
- lda DOSVEC
+sparta: lda DOSVEC
clc
adc #<LBUF
sta ptr1
adc #>LBUF
sta ptr1+1
- ldy #0
+cpcl0: ldy #0
cpcl: lda (ptr1),y
sta ourcl,y
iny
__getdefdev:
lda __dos_type ; which DOS?
- cmp #ATARIDOS
- beq finish
- cmp #MYDOS
- beq finish
+ cmp #XDOS
+ beq xdos ; only supported on XDOS ...
+; cmp #OSADOS+1 ; (redundant: #OSADOS+1 = #XDOS)
+ bcs finish ; ... and on OS/A+ and SpartaDOS
ldy #BUFOFF
lda #0
lda (DOSVEC),y
sta crvec+2
-crvec: jsr $FFFF ; will be set to crunch vector
+ jsr crvec
; Get default device
sta __defdev
iny
lda (DOSVEC),y
- sta __defdev+1
+done: sta __defdev+1
; Return pointer to default device
ldx #>__defdev
rts
+; XDOS version
+
+xdos: lda XDEFDEV
+ bne done
+
.data
+crvec: jmp $FFFF ; target address will be set to crunch vector
+
; Default device
__defdev:
--- /dev/null
+;
+; Christian Groessler, May-2016
+;
+; unsigned char _is_cmdline_dos(void);
+;
+; returns 0 for non-commandline DOS, 1 for commandline DOS
+;
+
+ .export __is_cmdline_dos
+ .import __dos_type
+ .include "atari.inc"
+
+__is_cmdline_dos:
+ ldx #0
+ lda __dos_type
+ cmp #MAX_DOS_WITH_CMDLINE + 1
+ txa
+ rol a
+ eor #$01
+ rts
pha
lda __dos_type
- beq not_impl ; AtariDOS
cmp #OSADOS+1
bcc do_sparta ; OS/A and SpartaDOS
+ cmp #MYDOS
+ bne not_impl ; neither MyDOS, OS/A, nor SpartaDOS
pla
- jmp __sysremove ; MyDOS and others (TODO: check XDOS)
+ jmp __sysremove ; MyDOS
not_impl:
pla
return NULL;
}
+static void exitfn(void)
+{
+ /* if DOS will automatically clear the screen, after the program exits, wait for a keypress... */
+ if (! _is_cmdline_dos())
+ cgetc();
+}
+
int main(int argc, char **argv)
{
char *filename, *x;
struct __iocb *iocb = findfreeiocb();
int iocb_num;
+ atexit(exitfn);
+
if (! iocb) {
fprintf(stderr, "couldn't find a free iocb\n");
- if (_dos_type != 1)
- cgetc();
return 1;
}
iocb_num = (iocb - &IOCB) * 16;
printf("\nfilename: ");
x = fgets(buf, 19, stdin);
printf("\n");
- if (! x)
+ if (! x) {
+ printf("empty filename, exiting...\n");
return 1;
+ }
if (*x && *(x + strlen(x) - 1) == '\n')
*(x + strlen(x) - 1) = 0;
+ if (! strlen(x)) { /* empty filename */
+ printf("empty filename, exiting...\n");
+ return 1;
+ }
filename = x;
}
else {
buffer = malloc(buflen);
if (! buffer) {
fprintf(stderr, "cannot alloc %ld bytes -- aborting...\n", (long)buflen);
- if (_dos_type != 1)
- cgetc();
return 1;
}
}
if (! file) {
free(buffer);
fprintf(stderr, "cannot open '%s': %s\n", filename, strerror(errno));
- if (_dos_type != 1)
- cgetc();
return 1;
}
file_err:
fclose(file);
free(buffer);
- if (_dos_type != 1)
- cgetc();
return 1;
}
if (filen > 32767l) {
if (regs.y != 1) {
fprintf(stderr, "CIO call to open cassette returned %d\n", regs.y);
free(buffer);
- if (_dos_type != 1)
- cgetc();
return 1;
}
regs.pc = 0xe456; /* CIOV */
_sys(®s);
- if (_dos_type != 1)
- cgetc();
return 1;
}
if (regs.y != 1) {
fprintf(stderr, "CIO call to close cassette returned %d\n", regs.y);
- if (_dos_type != 1)
- cgetc();
return 1;
}
/* all is fine */
printf("success\n");
- if (_dos_type != 1)
- cgetc();
return 0;
}
;-----------------------------------------------------------------------------
; All functions are available in the kernal jump table
-CINT = $FF81
-IOINIT = $FF84
-RAMTAS = $FF87
+CINT = $E518 ; No entries are in the kernal jump table of the Vic20 for these three (3) functions.
+IOINIT = $FDF9 ; The entries for these functions have been set to point directly to the functions
+RAMTAS = $FD8D ; in the kernal to maintain compatibility with the other Commodore platforms.
RESTOR = $FF8A
VECTOR = $FF8D
SETMSG = $FF90
#include "global.h"
#include "segments.h"
#include "stackptr.h"
+#include "stdfunc.h"
#include "textseg.h"
#include "util.h"
#include "codegen.h"
AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0));
AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Size);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size);
AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
}
}
AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0));
AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0));
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Size);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size);
AddCodeLine ("bne %s", LocalLabelName (CodeLabel));
} else {
- /* Use the easy way here: memcpy */
+ /* Use the easy way here: memcpy() */
g_getimmed (CF_STATIC, VarLabel, 0);
AddCodeLine ("jsr pushax");
g_getimmed (CF_STATIC, InitLabel, 0);
+void AddCmpCodeIfSizeNot256 (const char* Code, long Size)
+/* Add a line of Assembly code that compares an index register
+** only if it isn't comparing to #<256. (If the next line
+** is "bne", then this will avoid a redundant line.)
+*/
+{
+ if (Size != 256) {
+ AddCodeLine (Code, (unsigned int)Size);
+ }
+}
+
+
+
/*****************************************************************************/
/* memcpy */
/*****************************************************************************/
if (Arg3.Expr.IVal <= 127) {
AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
g_defcodelabel (Label);
if (Reg2) {
AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
} else {
AddCodeLine ("ldy #$00");
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
g_defcodelabel (Label);
if (Reg2) {
AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
}
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal));
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
} else {
AddCodeLine ("ldx #$00");
AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
AddCodeLine ("inx");
- AddCodeLine ("cpx #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
AddCodeLine ("lda (sp),y");
AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal));
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
} else {
AddCodeLine ("ldx #$00");
AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
AddCodeLine ("iny");
AddCodeLine ("inx");
- AddCodeLine ("cpx #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
AddCodeLine ("lda (sp),y");
AddCodeLine ("sta (ptr1),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
}
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
g_defcodelabel (Label);
AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal));
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
/* memset returns the address, so the result is actually identical
g_defcodelabel (Label);
AddCodeLine ("sta (ptr1),y");
AddCodeLine ("iny");
- AddCodeLine ("cpy #$%02X", (unsigned char) Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
+void AddCmpCodeIfSizeNot256 (const char* Code, long Size);
+/* Add a line of Assembly code that compares an index register
+** only if it isn't comparing to #<256. (If the next line
+** is "bne", then this will avoid a redundant line.)
+*/
+
int FindStdFunc (const char* Name);
/* Determine if the given function is a known standard function that may be
** called in a special way. If so, return the index, otherwise return -1.
/* End of stdfunc.h */
-
#endif
}
/* Not found or no identifier */
- CfgError (&CfgErrorPos, "%s expected", Name);
+ CfgError (&CfgErrorPos, "%s expected, got '%s'", Name, SB_GetConstBuf(&CfgSVal));
}
int main(void)
{
printf("default device: %s\n", _defdev);
- if (_dos_type != SPARTADOS && _dos_type != OSADOS) cgetc();
+ if (! _is_cmdline_dos()) cgetc();
return 0;
}
extern int getsp(void); /* comes from ../getsp.s */
-extern char _dos_type; /* bss variable */
unsigned char data = 0x12; /* data variable */
unsigned int *APPMHI = (unsigned int *)14; /* 14,15 */
printf(" sp: $%04X (stack ptr)\n", getsp());
if (allocmem) free(allocmem);
- if (_dos_type != 1) cgetc();
+ if (! _is_cmdline_dos()) cgetc();
return(0);
}