Browse Source

ZXCC Cleanup

- I know I said I was done, but I found some more stuff to clean up.  I think I am really done now.
pull/283/head
Wayne Warthen 4 years ago
parent
commit
2c0b818aba
  1. 2
      Binary/Apps/Makefile
  2. 6
      Tools/unix/zxcc/Build-VC.cmd
  3. 5
      Tools/unix/zxcc/config.h.windows
  4. 6
      Tools/unix/zxcc/cpmdrv.c
  5. 158
      Tools/unix/zxcc/cpmglob.c
  6. 69
      Tools/unix/zxcc/cpmint.h
  7. 2
      Tools/unix/zxcc/cpmparse.c
  8. 485
      Tools/unix/zxcc/cpmredir.c
  9. 3
      Tools/unix/zxcc/cpmredir.h
  10. 59
      Tools/unix/zxcc/dirent.c
  11. 16
      Tools/unix/zxcc/dirent.h
  12. 8
      Tools/unix/zxcc/drdos.c
  13. 22
      Tools/unix/zxcc/track.c
  14. 196
      Tools/unix/zxcc/util.c
  15. 8
      Tools/unix/zxcc/xlt.c
  16. 2
      Tools/unix/zxcc/z80.c
  17. 14
      Tools/unix/zxcc/zxbdos.c
  18. 1
      Tools/unix/zxcc/zxbdos.h
  19. 11
      Tools/unix/zxcc/zxcbdos.c
  20. 4
      Tools/unix/zxcc/zxcbdos.h
  21. 116
      Tools/unix/zxcc/zxcc.c
  22. 27
      Tools/unix/zxcc/zxcc.h
  23. 6
      Tools/unix/zxcc/zxdbdos.c
  24. 4
      Tools/unix/zxcc/zxdbdos.h
  25. BIN
      Tools/zxcc/zxcc-src.zip
  26. BIN
      Tools/zxcc/zxcc.exe
  27. BIN
      Tools/zxcc/zxccdbg.exe

2
Binary/Apps/Makefile

@ -8,4 +8,4 @@ all::
mkdir -p Tunes
clobber::
@rm -f *.bin *.com *.img *.rom *.pdf *.log *.eeprom *.ovr *.hlp *.doc *.COM *.BIN Tunes/*.mym Tunes/*.pt?
@rm -f *.bin *.com *.img *.rom *.pdf *.log *.eeprom *.ovr *.hlp *.doc *.COM *.BIN Tunes/*.mym Tunes/*.pt? Tunes/*.vgm

6
Tools/unix/zxcc/Build-VC.cmd

@ -5,7 +5,7 @@ setlocal
:: Visual Studio x86 Native Tools Command Prompt is assumed
::
:: Below configures VS2012 to target Windows XP and beyond
:: Below configures VS2012 to target Windows XP.
:: Not sure if it will work in later versions of VS, but seems
:: to do no harm.
set INCLUDE=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Include;%INCLUDE%
@ -16,10 +16,10 @@ set LINK=/SUBSYSTEM:CONSOLE,5.01 %LINK%
copy config.h.windows config.h
cl zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c
cl -I. zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c
if errorlevel 1 exit /b 255
cl /DDEBUG /Fe"zxccdbg.exe" zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c
cl -I. /DDEBUG /Fe"zxccdbg.exe" zxcc.c cpmdrv.c cpmglob.c cpmparse.c cpmredir.c drdos.c util.c xlt.c zxbdos.c zxcbdos.c zxdbdos.c z80.c dirent.c track.c
if errorlevel 1 exit /b 255
copy cpm\bios.bin .

5
Tools/unix/zxcc/config.h.windows

@ -1,5 +1,10 @@
#define HAVE_WINDOWS_H
#define HAVE_FCNTL_H
#ifdef _MSC_VER
#define HAVE_DIRENT_H
#endif
#define HAVE_DIRECT_H
#define HAVE_IO_H
#define WINVER _WIN32_WINNT_WINXP // target Windows XP
#define _WIN32_WINNT _WIN32_WINNT_WINXP // target Windows XP
//#define FILETRACKER 1

6
Tools/unix/zxcc/cpmdrv.c

@ -81,7 +81,7 @@ cpm_byte fcb_user (cpm_byte usr)
{
if (usr != 0xFF) redir_cpmuser = usr % 16;
redir_Msg("User: parameter %d returns %d\r\n", usr, redir_cpmuser);
DBGMSGV("User: parameter %d returns %d\n", usr, redir_cpmuser);
return redir_cpmuser;
}
@ -159,7 +159,6 @@ cpm_word fcb_getdpb(cpm_byte *dpb)
return 0x11;
}
/* Create an entirely bogus ALV
* TODO: Make it a bit better */
@ -181,6 +180,3 @@ cpm_word fcb_dfree (cpm_byte drive, cpm_byte *dma)
redir_wr24(dma, 0x8000L); /* 8MB / 128 / 2 */
return 0;
}

158
Tools/unix/zxcc/cpmglob.c

@ -25,7 +25,6 @@
#define S_ISDIR(mode) (((mode) & _S_IFDIR) != 0)
#endif
static cpm_byte* find_fcb;
static int find_n;
static int find_ext = 0;
@ -48,9 +47,11 @@ static char upper(char c)
* the naive code in the distributed zx will not work everywhere.
*/
/* Does the string "s" match the CP/M FCB? */
/* pattern[0-10] will become a CP/M name parsed from "s" if it matches. */
/* If 1st byte of FCB is '?' then anything matches. */
/*
* Does the string "s" match the CP/M FCB?
* pattern[0-10] will become a CP/M name parsed from "s" if it matches.
* If 1st byte of FCB is '?' then anything matches.
*/
static int cpm_match(char* s, cpm_byte* fcb, cpm_byte* pattern)
{
@ -65,6 +66,7 @@ static int cpm_match(char *s, cpm_byte *fcb, cpm_byte *pattern)
* the fcb. we reject any that can't be valid cp/m filenames,
* normalizing case as we go. all this goes into 'pattern'
*/
for (n = 0; n < 11; n++) pattern[n] = ' ';
/* The name must have 1 or 0 dots */
@ -74,7 +76,8 @@ static int cpm_match(char *s, cpm_byte *fcb, cpm_byte *pattern)
for (n = 0; n < m; n++) {
pattern[n] = upper(s[n]) & 0x7F;
}
} else { /* at least one dot */
}
else { /* at least one dot */
if (strchr(dotpos + 1, '.')) { /* More than 1 dot */
return 0;
}
@ -100,6 +103,7 @@ static int cpm_match(char *s, cpm_byte *fcb, cpm_byte *pattern)
* handle special case where fcb[0] == '?' or fcb[0] & 0x80
* this is used to return a full directory list on bdos's
*/
if (((fcb[0] & 0x7F) == '?') || (fcb[0] & 0x80)) {
return 1;
}
@ -114,7 +118,6 @@ static int cpm_match(char *s, cpm_byte *fcb, cpm_byte *pattern)
return 1; /* Success! */
}
/* Get the next entry from the host's directory matching "fcb" */
static struct dirent* next_entry(DIR* dir, cpm_byte* fcb, cpm_byte* pattern,
@ -131,26 +134,25 @@ static struct dirent * next_entry(DIR *dir, cpm_byte *fcb, cpm_byte *pattern,
for (unsatisfied = 1; unsatisfied; )
{
/* 1. Get the next entry */
en = readdir(dir);
if (!en) return NULL; /* No next entry */
++entryno; /* 0 for 1st, 1 for 2nd, etc. */
/* 2. See if it matches. We do this first (in preference to
seeing if it's a subdirectory first) because it doesn't
require disc access */
* seeing if it's a subdirectory first) because it doesn't
* require disc access */
if (!cpm_match(en->d_name, fcb, pattern))
{
continue;
}
/* 3. Stat it, & reject it if it's a directory */
/* 3. Stat it, & reject it if it's a directory */
strcpy(target_name, redir_drive_prefix[drv]);
strcat(target_name, en->d_name);
if (stat(target_name, st))
{
redir_Msg("Can't stat %s so omitting it.\n", target_name);
DBGMSGV("Can't stat %s so omitting it.\n", target_name);
continue; /* Can't stat */
}
if (S_ISDIR(st->st_mode))
@ -166,8 +168,6 @@ static struct dirent * next_entry(DIR *dir, cpm_byte *fcb, cpm_byte *pattern,
return en;
}
void volume_label(int drv, cpm_byte* dma)
{
struct stat st;
@ -176,6 +176,7 @@ void volume_label(int drv, cpm_byte *dma)
/* Get label name */
redir_get_label(drv, (char*)(dma + 1));
/* [0x0c] = label byte
* [0x0d] = password byte (=0)
* [0x10-0x17] = password
@ -193,7 +194,7 @@ void volume_label(int drv, cpm_byte *dma)
if (stat(redir_drive_prefix[drv], &st))
{
redir_Msg("stat() fails on '%s'\n", redir_drive_prefix[drv]);
DBGMSGV("stat() fails on '%s'\n", redir_drive_prefix[drv]);
return;
}
@ -201,8 +202,6 @@ void volume_label(int drv, cpm_byte *dma)
redir_wr32(dma + 0x1C, redir_cpmtime(st.st_mtime));
}
cpm_word redir_find(int n, cpm_byte* fcb, cpm_byte* dma)
{
DIR* hostdir;
@ -249,12 +248,10 @@ cpm_word redir_find(int n, cpm_byte *fcb, cpm_byte *dma)
return 0;
}
memset(dma, 0, 128); /* Zap the buffer */
/*
If returning all entries, return a volume label.
*/
/* If returning all entries, return a volume label. */
if ((fcb[0] & 0x7F) == '?')
{
if (!n)
@ -266,18 +263,18 @@ cpm_word redir_find(int n, cpm_byte *fcb, cpm_byte *dma)
}
/* Note: This implies that opendir() works on a filename with a
trailing slash. It does under Linux, but that's the only assurance
I can give.
*/
* trailing slash. It does under Linux, but that's the only assurance
* I can give. */
entryno = -1;
hostdir = opendir(redir_drive_prefix[drv]);
if (!hostdir)
{
redir_Msg("opendir() fails on '%s'\n", redir_drive_prefix[drv]);
DBGMSGV("opendir() fails on '%s'\n", redir_drive_prefix[drv]);
return 0xFF;
}
/* We have a handle to the directory. */
while (n >= 0)
{
@ -308,8 +305,6 @@ cpm_word redir_find(int n, cpm_byte *fcb, cpm_byte *dma)
if (attrib & 4) dma[10] |= 0x80; /* system */
if (!(attrib & 0x20)) dma[11] |= 0x80; /* archive */
/* TODO: Under Unix, work out correct RO setting */
recs = (st.st_size + 127) / 128;
@ -322,8 +317,7 @@ cpm_word redir_find(int n, cpm_byte *fcb, cpm_byte *dma)
dma[0x12] = entryno & 0xFF;
redir_wr32(dma + 0x16, (dword)st.st_mtime); /* Modification time. */
/* TODO: It should be in DOS */
/* format */
/* TODO: It should be in DOS format */
/* TODO: At 0x1A, 1st cluster */
redir_wr32(dma + 0x1C, st.st_size); /* True size */
@ -348,25 +342,13 @@ cpm_word redir_find(int n, cpm_byte *fcb, cpm_byte *dma)
return 0;
}
#ifdef DEBUG
#define SHOWNAME(func) \
{ \
char fname[CPM_MAXPATH]; \
redir_fcb2unix(fcb, fname); \
redir_Msg(func "(\"%s\")\n", fname); \
}
#else
#define SHOWNAME(func)
#endif
cpm_word fcb_find1(cpm_byte* fcb, cpm_byte* dma) /* 0x11 */
{
#ifdef DEBUG
int rv;
#endif
SHOWNAME("fcb_find1")
FCBENT(fcb);
redir_log_fcb(fcb);
@ -374,17 +356,18 @@ cpm_word fcb_find1 (cpm_byte *fcb, cpm_byte *dma) /* 0x11 */
find_fcb = fcb;
find_ext = 0;
find_xfcb = 0;
#ifdef DEBUG
rv = redir_find(find_n, fcb, dma);
if (rv < 4)
{
redir_Msg("Ret: %-11.11s\n", dma + 1);
DBGMSGV("Ret: %-11.11s\n", dma + 1);
}
else redir_Msg("Ret: Fail\n");
return rv;
else DBGMSG("Ret: Fail\n");
FCBRET(rv);
#else
return redir_find(find_n, find_fcb, dma);
FCBRET(redir_find(find_n, find_fcb, dma));
#endif
}
@ -396,23 +379,29 @@ cpm_word fcb_find2 (cpm_byte *fcb, cpm_byte *dma) /* 0x12 */
{
#ifdef DEBUG
int rv;
char fname[CPM_MAXPATH];
#endif
FCBENT(find_fcb);
#ifdef DEBUG
redir_fcb2unix(find_fcb, fname);
redir_Msg("fcb_find2(\"%s\") no. %d\n", fname, find_n);
DBGMSGV("file number %d, '%s'\n", find_n, fname);
#endif
++find_n;
#ifdef DEBUG
rv = redir_find(find_n, find_fcb, dma);
if (rv < 4)
{
redir_Msg("Ret: %-11.11s\n", dma + 1);
DBGMSGV("Ret: %-11.11s\n", dma + 1);
}
else redir_Msg("Ret: Fail\n");
return rv;
else DBGMSG("Ret: Fail\n");
FCBRET(rv);
#else
return redir_find(find_n, find_fcb, dma);
FCBRET(redir_find(find_n, find_fcb, dma));
#endif
}
@ -427,8 +416,9 @@ cpm_word fcb_unlink(cpm_byte *fcb, cpm_byte *dma)
int handle = 0;
int unpasswd = 0;
char fname[CPM_MAXPATH];
int del_cnt = 0;
SHOWNAME("fcb_unlink")
FCBENT(fcb);
if (fcb[5] & 0x80) unpasswd = 1; /* Remove password rather than file */
@ -438,25 +428,30 @@ cpm_word fcb_unlink(cpm_byte *fcb, cpm_byte *dma)
if (!drv || drv == '?') drv = redir_cpmdrive;
else drv--;
if (redir_ro_drv(drv)) return 0x02FF; /* Error: R/O drive */
if (redir_ro_drv(drv))
{
/* Error: R/O drive */
DBGMSG("delete failed - R/O drive\n");
FCBRET(0x02FF);
}
#ifdef DEBUG
redir_fcb2unix(fcb, fname);
redir_Msg("fcb_unlink(\"%s\")\n", fname);
DBGMSGV("fcb_unlink('%s')\n", fname);
#endif
/* Note: This implies that opendir() works on a filename with a
trailing slash. It does under Linux, but that's the only assurance
I can give.
*/
* trailing slash. It does under Linux, but that's the only assurance
* I can give.*/
hostdir = opendir(redir_drive_prefix[drv]);
if (!hostdir)
{
redir_Msg("opendir() fails on '%s'\n", redir_drive_prefix[drv]);
return 0xFF;
DBGMSGV("opendir failed on '%s'\n", redir_drive_prefix[drv]);
FCBRET(0xFF);
}
/* We have a handle to the directory. */
do
{
@ -465,7 +460,7 @@ cpm_word fcb_unlink(cpm_byte *fcb, cpm_byte *dma)
{
strcpy(target_name, redir_drive_prefix[drv]);
strcat(target_name, de->d_name);
redir_Msg("Deleting %s\n", de->d_name);
DBGMSGV("deleting '%s'\n", de->d_name);
if (unpasswd)
{
#ifdef __MSDOS__
@ -478,44 +473,59 @@ cpm_word fcb_unlink(cpm_byte *fcb, cpm_byte *dma)
}
else if (fcb[0] & 0x80)
{
DBGMSGV("rmdir '%s'\n", target_name);
handle = rmdir(target_name);
if (handle && redir_password_error())
{
DBGMSGV("rmdir failed (errno=%lu): %s\n", errno, strerror(errno));
redir_password_append(target_name, dma);
DBGMSGV("rmdir '%s'\n", target_name);
handle = rmdir(target_name);
}
if (handle)
DBGMSGV("rmdir failed (errno=%lu): %s\n", errno, strerror(errno));
}
else
{
releaseFile(target_name);
DBGMSGV("unlink '%s'\n", target_name);
handle = unlink(target_name);
if (handle && redir_password_error())
{
DBGMSGV("unlink failed (errno=%lu): %s\n", errno, strerror(errno));
redir_password_append(target_name, dma);
releaseFile(target_name);
DBGMSGV("unlink '%s'\n", target_name);
handle = unlink(target_name);
}
if (handle)
DBGMSGV("unlink failed (errno=%lu): %s\n", errno, strerror(errno));
}
if (handle) de = NULL; /* Delete failed */
}
}
while (de != NULL);
if (handle)
de = NULL; /* Delete failed */
else
del_cnt++;
}
} while (de != NULL);
if (!handle && !del_cnt)
DBGMSG("no matching directory entries\n");
else
DBGMSGV("deleted %i file(s)\n", del_cnt);
if (handle || !del_cnt)
{
redir_Msg("Ret: -1\n");
DBGMSG("delete processing failed\n");
closedir(hostdir);
return 0xFF;
FCBRET(0xFF);
}
redir_Msg("Ret: 0\n");
DBGMSG("delete processing succeeded\n");
closedir(hostdir);
return 0;
FCBRET(0);
}
#ifdef __MSDOS__
cpm_word redir_get_label(cpm_byte drv, char* pattern)
{
@ -585,6 +595,4 @@ cpm_word redir_get_label(cpm_byte drv, char *pattern)
return 0;
}
#endif

69
Tools/unix/zxcc/cpmint.h

@ -20,13 +20,7 @@
This file holds internal declarations for the library.
*/
#ifndef _WIN32
#include "config.h"
#define DIRSEP "/"
#else
#include "config.h"
#define DIRSEP "/\\:"
#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@ -47,16 +41,12 @@
#include <errno.h>
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#ifdef HAVE_DIRECT_H
#include <direct.h>
#endif
#else
#ifdef __WATCOMC__
#ifdef HAVE_IO_H
#include <io.h>
#include <direct.h>
#else
#include "dirent.h"
#endif
#endif
#ifdef HAVE_NDIR_H
#include <ndir.h>
@ -94,20 +84,32 @@
/* MSDOS includes removed */
#ifdef _WIN32
#define DIRSEP "/"
#define mkdir(dir, mode) _mkdir(dir)
#define strcasecmp _stricmp
int truncate(const char* path, off_t length); /* see util.c */
#define ftruncate _chsize
/* note Windows build assumes Windows is configured as a non case sensitive filesystem */
#ifndef STDIN_FILENO
#define STDIN_FILENO _fileno(stdin)
#define STDOUT_FILENO _fileno(stdout)
#define STDERR_FILENO _fileno(stderr)
#endif
#else
#define DIRSEP "/\\:"
#define CASE_SENSITIVE_FILESYSTEM 1
#endif
#include "cpmredir.h"
#ifdef _WIN32
int truncate(const char* path, off_t length); /* see util.c */
#endif
typedef unsigned char byte; /* Must be exactly 8 bits */
typedef unsigned short word; /* Must be exactly 16 bits */
typedef unsigned long dword; /* Must be at least 32 bits, and
>= sizeof(int) */
#include "cpmredir.h"
#ifdef CPMDEF
#define EXT
#define INIT(x) =x
@ -146,8 +148,6 @@ EXT cpm_word redir_ro_drives INIT(0);
#undef EXT
#undef INIT
/* Convert FCB to a Unix filename, returning 1 if it's ambiguous */
int redir_fcb2unix(cpm_byte* fcb, char* fname);
@ -163,21 +163,46 @@ int redir_verify_fcb(cpm_byte *fcb);
/* Facilities for debug tracing */
long zxlseek(int fd, long offset, int wh);
#ifdef _WIN32
char* GetErrorStr(DWORD);
#endif
#ifdef DEBUG
// long zxlseek(int fd, long offset, int wh);
void redir_Msg(char *s, ...);
// void redir_Msg(char *s, ...);
void DbgMsg(const char* file, int line, const char* func, char* s, ...);
void redir_showfcb(cpm_byte* fcb);
#else
// #define zxlseek lseek
/* Warning: This is a GCC extension */
#define redir_Msg(x, ...)
// #define redir_Msg(x, ...)
#define redir_showfcb(x)
#endif
#ifdef DEBUG
#define FCBENT(fcb) \
{ \
char fname[CPM_MAXPATH] = ""; \
redir_fcb2unix(fcb, fname); \
DBGMSGV("entry w/ FCB @ 0x%04X, filename:'%s'\n", fcb-RAM, fname); \
}
#define FCBRET(rc) \
{ \
DBGMSGV("returning 0x%04X\n", rc); \
return rc; \
}
#define DBGMSGV(s, ...) DbgMsg(__FILE__, __LINE__, __func__, s, __VA_ARGS__)
#define DBGMSG(s) DbgMsg(__FILE__, __LINE__, __func__, s)
#else
#define FCBENT(fcb)
#define FCBRET(rc) return rc;
#define DBGMSGV(s, ...)
#define DBGMSG(s)
#endif
/* Get the "sequential access" file pointer out of an FCB */
@ -192,7 +217,6 @@ dword redir_cpmtime(time_t t);
/* And back */
time_t redir_unixtime(cpm_byte* c);
/* Functions to access 24-bit & 32-bit words in memory. These are always
little-endian. */
@ -223,7 +247,6 @@ cpm_word redir_xlt_err(void);
/* Get disc label */
cpm_word redir_get_label(cpm_byte drv, char* pattern);
/* DRDOS set/get access rights - no-ops under MSDOS and Unix:
*
* CP/M password mode -> DRDOS password mode */
@ -247,3 +270,5 @@ void redir_password_append(char *s, cpm_byte *dma);
void releaseFile(char* fname);
int trackFile(char* fname, void* fcb, int fd);
#define releaseFCB(fcb) trackFile(NULL, fcb, -1)
extern byte RAM[65536]; /* The Z80's address space */

2
Tools/unix/zxcc/cpmparse.c

@ -50,8 +50,6 @@ static int parse_drive_user(char *txt, cpm_byte *fcb)
return 0;
}
cpm_word fcb_parse(char* txt, cpm_byte* fcb)
{
int nl = 0, tl = 0, pl = 0, phase = 0;

485
Tools/unix/zxcc/cpmredir.c

File diff suppressed because it is too large

3
Tools/unix/zxcc/cpmredir.h

@ -86,7 +86,6 @@ int xlt_umap(int drive);
char* xlt_getcwd(int drive);
/* BDOS functions. Eventually this should handle all disc-related BDOS
* functions.
*
@ -143,9 +142,9 @@ cpm_word fcb_sdate (cpm_byte *fcb, cpm_byte *dma); /* 0x74 */
cpm_word fcb_parse(char* txt, cpm_byte* fcb); /* 0x98 */
/* fcb_parse returns length of filename parsed, 0 if EOL, 0xFFFF if error */
#ifdef __cplusplus
}
#endif
#endif /* def CPMREDIR_H_INCLUDED */

59
Tools/unix/zxcc/dirent.c

@ -7,10 +7,9 @@
Rights: See end of file.
*/
#pragma warning(disable : 4996)
#include "dirent.h"
#include <errno.h>
#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
#include <stdlib.h>
#include <string.h>
@ -19,35 +18,20 @@ extern "C"
{
#endif
//typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
typedef long handle_type; /* C99's intptr_t not sufficiently portable */
struct DIR
{
handle_type handle; /* -1 for failed rewind */
struct _finddata_t info;
struct dirent result; /* d_name null iff first time */
char *name; /* null-terminated char string */
};
DIR *opendir(const char *name)
{
DIR* opendir(const char* name) {
DIR* dir = 0;
if(name && name[0])
{
if (name && name[0]) {
size_t base_length = strlen(name);
const char* all = /* search pattern must end with suitable wildcard */
strchr("/\\", name[base_length - 1]) ? "*" : "/*";
if ((dir = (DIR*)malloc(sizeof * dir)) != 0 &&
(dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
{
(dir->name = (char*)malloc(base_length + strlen(all) + 1)) != 0) {
strcat(strcpy(dir->name, name), all);
if ((dir->handle =
(handle_type) _findfirst(dir->name, &dir->info)) != -1)
{
(handle_type)_findfirst(dir->name, &dir->info)) != -1) {
dir->result.d_name = 0;
}
else /* rollback */
@ -64,22 +48,18 @@ DIR *opendir(const char *name)
errno = ENOMEM;
}
}
else
{
else {
errno = EINVAL;
}
return dir;
}
int closedir(DIR *dir)
{
int closedir(DIR* dir) {
int result = -1;
if(dir)
{
if(dir->handle != -1)
{
if (dir) {
if (dir->handle != -1) {
result = _findclose(dir->handle);
}
@ -95,36 +75,29 @@ int closedir(DIR *dir)
return result;
}
struct dirent *readdir(DIR *dir)
{
struct dirent* readdir(DIR* dir) {
struct dirent* result = 0;
if(dir && dir->handle != -1)
{
if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
{
if (dir && dir->handle != -1) {
if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) {
result = &dir->result;
result->d_name = dir->info.name;
}
}
else
{
else {
errno = EBADF;
}
return result;
}
void rewinddir(DIR *dir)
{
if(dir && dir->handle != -1)
{
void rewinddir(DIR* dir) {
if (dir && dir->handle != -1) {
_findclose(dir->handle);
dir->handle = (handle_type)_findfirst(dir->name, &dir->info);
dir->result.d_name = 0;
}
else
{
else {
errno = EBADF;
}
}

16
Tools/unix/zxcc/dirent.h

@ -11,18 +11,26 @@
*/
#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct DIR DIR;
struct dirent
{
struct dirent {
char *d_name;
};
typedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
typedef struct {
handle_type handle; /* -1 for failed rewind */
struct _finddata_t info;
struct dirent result; /* d_name null iff first time */
char *name; /* null-terminated char string */
} DIR;
DIR *opendir(const char *);
int closedir(DIR *);
struct dirent *readdir(DIR *);

8
Tools/unix/zxcc/drdos.c

@ -198,7 +198,7 @@ cpm_word redir_password_error(void)
intdos(&r, &r);
redir_Msg("Last error was: %04x\r\n", r.w.ax);
redir_Msg("Last error was: %04x\n", r.w.ax);
if (r.w.ax == 0x56) return 1; /* Bad password */
return 0;
@ -229,8 +229,8 @@ void redir_password_append(char *s, cpm_byte *dma)
void redir_password_append(char* s, cpm_byte* dma) {}
cpm_word redir_password_error(void) { return 0; }
cpm_word redir_drdos_put_rights(char* path, cpm_byte* dma, cpm_word rights)
{ return 0; }
{
return 0;
}
cpm_word redir_drdos_get_rights(char* path) { return 0; }
#endif /* __MSDOS__ */

22
Tools/unix/zxcc/track.c

@ -22,8 +22,8 @@
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//#include "cpmint.h"
#include "zxcc.h"
#include "cpmint.h"
/* CP/M does not require that files opened for reading need to be closed,
* this has two impacts
@ -81,8 +81,22 @@
* a problem. I am not aware of any real programs that do this.
* Please let me know if the situation arises.
*/
/* windows needs to use file tracking, for unix/linux it is optional */
/*
* The FILETRACKER functionality was implemented primarily because
* MSDOS file interface does not allow opening files in shared mode.
* This port of zxcc deprecates MSDOS and uses WIN32 API calls to handle
* all file I/O. So, this means that FILETRACKER is now optional for
* for Windows as well as Unix. I have found some edge cases where
* FILETRACKER caused a CP/M program to misbehave. Specifically, ZSM4
* reuses FCBs if files are included and does it such a way that the
* FILETRACKER is unable to solve the problem. For maximum
* compatibility, FILETRACKER may now be left off with the implication
* that a lot of file handles will be left open.
*/
#ifdef FILETRACKER
typedef struct _track {
struct _track* next;
int handle;
@ -111,7 +125,6 @@ void releaseFile(char* fname) {
s = s->next;
}
int trackFile(char* fname, void* fcb, int fd) {
track_t* s = (track_t*)&openFiles;
Msg("trackFile: \"%s\", FCB=0x%X, Handle=%i\n", fname, (byte*)fcb - RAM, fd);
@ -147,4 +160,3 @@ void releaseFile(char* fname) {}
int trackFile(char* fname, void* fcb, int fd) { return fd; }
#endif

196
Tools/unix/zxcc/util.c

@ -22,52 +22,68 @@
#include "cpmint.h"
#ifdef _WIN32
char* GetErrorStr(dword dwErr)
{
LPVOID lpMsgBuf;
static char ErrStr[256] = "";
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL,
dwErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
sizeof(ErrStr), NULL);
strncpy(ErrStr, lpMsgBuf, sizeof(ErrStr));
LocalFree(lpMsgBuf);
/* In debug mode, lseek()s can be traced. */
return ErrStr;
}
#ifdef DEBUG
#endif
char* whence(int wh)
{
switch (wh)
{
case SEEK_SET: return("SEEK_SET");
case SEEK_CUR: return("SEEK_CUR");
case SEEK_END: return("SEEK_END");
default: return("SEEK_???");
}
}
/* In debug mode, lseek()s can be traced. */
long zxlseek(int fd, long offset, int wh)
{
#ifdef _WIN32
long v;
redir_Msg(">SetFilePointer() Handle=%lu, Offset=%lu, Method=%lu\n", fd, offset, wh);
DBGMSGV("seek on file #%i to 0x%lX using %s\n", fd, offset, whence(wh));
v = SetFilePointer((HANDLE)fd, offset, NULL, wh);
redir_Msg("<SetFilePointer() FilePos=%lu, LastErr=%lu\n", v, GetLastError());
if (v == INVALID_SET_FILE_POINTER)
if (v != INVALID_SET_FILE_POINTER) return v;
DBGMSGV("seek failed (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError()));
return -1;
return v;
#else
DBGMSGV("seek on #%i to 0x%lX using %s\n", fd, offset, whence(wh));
long v = lseek(fd, offset, wh);
if (v >= 0) return v;
redir_Msg("lseek fails with errno = %d\n", errno);
if (errno == EBADF) redir_Msg(" (bad file descriptor %d)\n", fd);
if (errno == ESPIPE) redir_Msg(" (file %d is a pipe)\n", fd);
if (errno == EINVAL) redir_Msg(" (bad parameter %d)\n", wh);
DBGMSGV("seek failed (errno=%lu): %s\n", errno, strerror(errno));
return -1;
#endif
}
#else
long zxlseek(int fd, long offset, int wh)
{
#ifdef _WIN32
return SetFilePointer((HANDLE)fd, offset, NULL, wh);
#else
return lseek(fd, offset, wh);
#endif
}
#endif
#ifdef DEBUG
void redir_showfcb(cpm_byte* fd)
@ -79,7 +95,7 @@ void redir_showfcb(cpm_byte *fd)
if (!n || n >= 12) printf("%02x ", fd[n]);
else printf("%c", fd[n] & 0x7F);
}
printf("\r\n");
printf("\n");
}
#endif
@ -104,7 +120,6 @@ void redir_put_fcb_pos(cpm_byte *fcb, long npos)
fcb[0x0E] = (npos / 524288L) % 64; /* S2 */
}
/*
* find a filename that works.
* note that this is where we handle the case sensitivity/non-case sensitivity
@ -112,8 +127,7 @@ void redir_put_fcb_pos(cpm_byte *fcb, long npos)
* the name that is passed in should be in lower case.
* we'll modify it to the first one that matches
*/
void
swizzle(char *fullpath)
void swizzle(char* fullpath)
{
struct stat ss;
char* slash;
@ -148,6 +162,7 @@ int redir_fcb2unix(cpm_byte *fcb, char *fname)
{
int n, q, drv, ddrv;
char s[2];
char buf[256];
s[1] = 0;
q = 0;
@ -157,11 +172,6 @@ int redir_fcb2unix(cpm_byte *fcb, char *fname)
ddrv = fcb[0] & 0x7F;
if (ddrv < 0x1F) ddrv += '@';
redir_Msg("%c:%-8.8s.%-3.3s\n",
ddrv,
fcb + 1,
fcb + 9);
if (!drv) strcpy(fname, redir_drive_prefix[redir_cpmdrive]);
else strcpy(fname, redir_drive_prefix[drv - 1]);
@ -176,6 +186,16 @@ int redir_fcb2unix(cpm_byte *fcb, char *fname)
strcat(fname, s);
}
}
sprintf(buf, "'%c:%-8.8s.%-3.3s' --> '%s'", ddrv, fcb + 1, fcb + 9, fname);
for (n = 0; buf[n] != '\0'; n++)
{
buf[n] &= 0x7F;
if (buf[n] < ' ') buf[n] = 'x';
}
DBGMSGV("%s\n", buf);
return q;
}
@ -188,49 +208,83 @@ int redir_ofile(cpm_byte *fcb, char *s)
int h;
/* Software write-protection */
#ifdef _WIN32
redir_Msg(">CreateFile([OPEN_EXISTING]) Name='%s'\n", s);
releaseFCB(fcb);
if (!redir_ro_fcb(fcb))
{
// Attempt to open existing file with read/write access
DBGMSGV("open existing file '%s' with read/write access\n", s);
h = (int)CreateFile(s, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
redir_Msg("<CreateFile([OPEN_EXISTING]) Handle=%lu, LastErr=%lu\n", h, GetLastError());
if (h != HFILE_ERROR)
{
DBGMSGV("file '%s' opened R/W as #%i\n", s, h);
return trackFile(s, fcb, h);
}
DBGMSGV("open R/W failed (errno=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError()));
}
// Attempt to open existing file with read-only access
DBGMSGV("open existing file '%s' with read-only access\n", s);
h = (int)CreateFile(s, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == HFILE_ERROR)
{
redir_Msg("Returning -1\n");
DBGMSGV("open R/O failed (errno=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError()));
return -1;
}
DBGMSGV("file '%s' opened R/O as #%i\n", s, h);
fcb[9] |= 0x80;
#else
#ifdef __MSDOS__
#elif defined(__MSDOS__)
int rv;
if (!redir_ro_fcb(fcb))
{
rv = _dos_open(s, O_RDWR, &h);
if (!rv) return h;
redir_Msg("Open of %s fails: error %x\r\n", s, rv);
DBGMSGV("Open of %s fails: error %x\n", s, rv);
}
rv = _dos_open(s, O_RDONLY, &h);
if (rv) return -1;
fcb[9] |= 0x80;
#else
releaseFCB(fcb);
releaseFCB(fcb);
swizzle(s);
if (!redir_ro_fcb(fcb))
{
// Attempt to open existing file with read/write access
DBGMSGV("open existing file '%s' with read/write access\n", s);
h = open(s, O_RDWR | O_BINARY);
if (h >= 0 || (errno != EACCES && errno != EROFS))
{
DBGMSGV("file '%s' opened R/W as #%i\n", s, h);
return trackFile(s, fcb, h);
}
DBGMSGV("failed to open R/W (errno=%lu): %s\n", errno, strerror(errno));
}
// Attempt to open existing file with read-only access
DBGMSGV("open existing file '%s' with read-only access\n", s);
h = open(s, O_RDONLY | O_BINARY);
if (h < 0) return -1;
if (h < 0)
{
DBGMSGV("failed to open R/O (errno=%lu): %s\n", errno, strerror(errno));
return -1;
}
DBGMSGV("file '%s' opened R/O as #%i\n", s, h);
fcb[9] |= 0x80;
#endif
#endif
return trackFile(s, fcb, h);
}
/* Extract a file handle from where it was stored in an FCB by fcb_open()
or fcb_creat(). Aborts if the FCB has been tampered with.
@ -245,19 +299,18 @@ int redir_verify_fcb(cpm_byte *fcb)
return -1;
}
return (int)(redir_rd32(fcb + 18));
}
/* Print a trace message */
#ifdef DEBUG
void redir_Msg(char *s, ...)
void DbgMsg(const char* file, int line, const char* func, char* s, ...)
{
va_list ap;
va_start(ap, s);
fprintf(stderr, "cpmredir trace: ");
fprintf(stderr, "%s(%s@%i): ", func, file, line);
vfprintf(stderr, s, ap);
va_end(ap);
fflush(stderr);
@ -304,7 +357,6 @@ time_t redir_unixtime(cpm_byte *c)
#undef UNBCD
/* Functions to access 24-bit & 32-bit words in memory. These are always
little-endian. */
@ -332,7 +384,6 @@ dword redir_rd24(cpm_byte *addr)
return rv;
}
dword redir_rd32(cpm_byte* addr)
{
register dword rv = addr[3];
@ -343,7 +394,6 @@ dword redir_rd32(cpm_byte *addr)
return rv;
}
void redir_log_drv(cpm_byte drv)
{
if (!drv) redir_l_drives |= 1;
@ -358,7 +408,6 @@ void redir_log_fcb(cpm_byte *fcb)
else redir_log_drv(redir_cpmdrive);
}
int redir_ro_drv(cpm_byte drv)
{
if (!drv) return redir_ro_drives & 1;
@ -373,11 +422,10 @@ int redir_ro_fcb(cpm_byte *fcb)
else return redir_ro_drv(redir_cpmdrive);
}
cpm_word redir_xlt_err(void)
{
if (redir_password_error()) return 0x7FF; /* DRDOS pwd error */
switch (errno)
{
case EISDIR:
@ -389,20 +437,48 @@ cpm_word redir_xlt_err(void)
}
}
#ifdef _WIN32
/* minimal implementation of truncate */
int truncate(const char* path, off_t length)
{
int result;
int fd = open(path, O_BINARY | O_RDWR);
BOOL bResult;
HANDLE hFile;
DWORD dwOffset;
DBGMSGV("truncate file %s to %lu\n", path, length);
if (fd < 0)
hFile = CreateFile(path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
DBGMSGV("truncate failed to open file (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError()));
return -1;
result = ftruncate(fd, length);
return close(fd) == 0 && result == 0 ? 0 : -1;
}
dwOffset = SetFilePointer(hFile, length, NULL, FILE_BEGIN);
if (dwOffset == INVALID_SET_FILE_POINTER)
{
DBGMSGV("truncate failed to open file (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError()));
CloseHandle(hFile);
return -1;
}
bResult = SetEndOfFile(hFile);
if (!bResult)
{
DBGMSGV("truncate failed to set end of file (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError()));
CloseHandle(hFile);
return -1;
}
bResult = CloseHandle(hFile);
if (!bResult)
{
DBGMSGV("truncate failed to close file (Error=%lu): %s\n", GetLastError(), GetErrorStr(GetLastError()));
return -1;
}
DBGMSGV("truncate set file length to %lu\n", dwOffset);
return 0;
}
#endif

8
Tools/unix/zxcc/xlt.c

@ -40,7 +40,7 @@ static void drdos_init(void)
__dpmi_int(0x21, &ir);
if (ir.x.flags & 1) return; /* Not DRDOS */
redir_Msg("DRDOS detected.\r\n");
redir_Msg("DRDOS detected.\n");
redir_drdos = 1;
@ -53,15 +53,13 @@ static void drdos_init(void)
intdos(&ir, &or );
if (or .w.cflag) return; /* Not DRDOS */
redir_Msg("DRDOS detected.\r\n");
redir_Msg("DRDOS detected.\n");
redir_drdos = 1;
#endif /* __GO32__ */
}
#endif /* __MSDOS__ */
int fcb_init(void)
{
int n;
@ -181,7 +179,6 @@ int xlt_map(int drive, char *localdir)
return 1;
}
/* Unmap a drive
*/
@ -192,7 +189,6 @@ int xlt_umap(int drive)
return 1;
}
char* xlt_getcwd(int drive)
{
if (drive < 0 || drive > 16) return "";

2
Tools/unix/zxcc/z80.c

@ -123,7 +123,7 @@ void mainloop(word spc, word ssp){
// if (pc == 0x1177) tr = 1;
// if (pc == 0x1185) tr = 0;
if (tr >= 1) ++id;
if (tr >= 1) printf("%d: PC=%04x %02x AF=%02x:%02x BC=%04x DE=%04x HL=%04x IX=%04x IY=%04x\r\n",
if (tr >= 1) printf("%d: PC=%04x %02x AF=%02x:%02x BC=%04x DE=%04x HL=%04x IX=%04x IY=%04x\n",
id, pc, fetch(pc), a,f, bc, de, hl, ix, iy);
}
*/

14
Tools/unix/zxcc/zxbdos.c

@ -134,7 +134,7 @@ void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f,
word temp;
int retv;
Msg("BDOS service invoked: C=%02x DE=%04x\n", *c, de);
DBGMSGV("BDOS service invoked: C=0x%02X DE=0x%04X\n", *c, de);
switch (*c)
{
@ -263,7 +263,7 @@ void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f,
break;
case 0x1A: /* Set DMA */
Msg("Set DMA to %04x\n", de);
DBGMSGV("Set DMA to 0x%04X\n", de);
cpm_dma = de;
break;
@ -287,7 +287,7 @@ void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f,
case 0x1F: /* Get DPB */
fcb_getdpb(RAM + 0xFFC0);
setw(l, h, 0xFFC0);
break; /* Whoops. Missed that 'break'. */
break;
case 0x20: /* Get/set uid */
setw(l, h, fcb_user(*e));
@ -331,7 +331,7 @@ void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f,
case 0x2E:
setw(l, h, fcb_dfree(*e, pdma));
break; /* Whoops. Missed that 'break'. */
break;
/* 0x2F: Chain */
@ -478,14 +478,12 @@ void cpmbdos(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f,
*b = *h;
}
void cpmbios(byte* a, byte* b, byte* c, byte* d, byte* e, byte* f,
byte* h, byte* l, word* pc, word* ix, word* iy)
{
int func = (((*ix) & 0xFF) / 3) - 1;
Msg("BIOS service invoked: func=%02x\n", func);
DBGMSGV("BIOS service invoked: func=0x%02X\n", func);
switch (func) /* BIOS function */
{
@ -533,7 +531,7 @@ void cpmbios(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f,
#ifdef USE_CPMIO
cpm_bdos_110('$');
cpm_bdos_9("This program has attempted to call USERF, "
"which is not implemented\r\n$");
"which is not implemented\n$");
#else
printf("This program has attempted to call USERF, which "
"is not implemented.\n");

1
Tools/unix/zxcc/zxbdos.h

@ -47,4 +47,3 @@ void gsxwr(gsx_word addr, gsx_byte value);
void cpmbdos();
void cpmbios();

11
Tools/unix/zxcc/zxcbdos.c

@ -2,18 +2,9 @@
#include "zxbdos.h"
#include "zxcbdos.h"
#ifndef _WIN32
#include <sys/ioctl.h>
#endif
#ifdef _WIN32
#include <conio.h>
#endif
/* Line input */
#ifdef USE_CPMIO
void bdos_rdline(word line, word* PC)
{
unsigned char* buf;
@ -72,7 +63,7 @@ void bdos_rdline(word line, word *PC)
//RAM[line + 1] = strlen((char *)(RAM + line + 2)) - 1;
RAM[line + 1] = (unsigned char)n;
Msg("Input: [%d] %-*.*s\n", RAM[line + 1], RAM[line + 1], RAM[line +1], (char *)(RAM+line+2));
DBGMSGV("Input: [%d] %-*.*s\n", RAM[line + 1], RAM[line + 1], RAM[line + 1], (char*)(RAM + line + 2));
}
#endif /* ndef USE_CPMIO */

4
Tools/unix/zxcc/zxcbdos.h

@ -1,4 +1,6 @@
void bdos_rdline(word line, word* PC);
int cpm_bdos_6(byte e);
byte cin(void);
void cout(byte);
int cstat(void);

116
Tools/unix/zxcc/zxcc.c

@ -14,6 +14,10 @@ char bindir80[CPM_MAXPATH] = "";
char libdir80[CPM_MAXPATH] = "";
char incdir80[CPM_MAXPATH] = "";
#ifndef _WIN32
struct termios tc_orig;
#endif
byte RAM[65536]; /* The Z80's address space */
void load_comfile(void); /* Forward declaration */
@ -21,13 +25,6 @@ void load_comfile(void); /* Forward declaration */
static int deinit_term, deinit_gsx;
static void mkpath(char* fullpath, char* path, char* subdir);
#ifndef _WIN32
struct termios tc_orig;
void raw_init(void);
void deinit_raw(void);
#endif
void dump_regs(FILE* fp, byte a, byte b, byte c, byte d, byte e, byte f,
byte h, byte l, word pc, word ix, word iy)
{
@ -36,8 +33,6 @@ void dump_regs(FILE *fp, byte a, byte b, byte c, byte d, byte e, byte f,
a, f, b, c, d, e, h, l, pc, ix, iy);
}
char* parse_to_fcb(char* s, int afcb)
{
byte* fcb = &RAM[afcb + 1];
@ -74,21 +69,6 @@ char *parse_to_fcb(char *s, int afcb)
return s;
}
void Msg(char *s, ...)
{
#ifdef DEBUG
va_list ap;
va_start(ap, s);
fprintf(stderr, "%s trace: ", progname);
vfprintf(stderr, s, ap);
fflush(stderr);
va_end(ap);
#endif
}
void ed_fe(byte* a, byte* b, byte* c, byte* d, byte* e, byte* f,
byte* h, byte* l, word* pc, word* ix, word* iy)
{
@ -120,7 +100,6 @@ void ed_fe(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f,
}
}
/*
* load_bios() loads the minimal CP/M BIOS and BDOS.
*
@ -172,7 +151,7 @@ void load_bios(void)
}
fclose(fp);
Msg("Loaded %d bytes of BIOS\n", bios_len);
DBGMSGV("Loaded %d bytes of BIOS\n", bios_len);
}
/*
* try_com() attempts to open file, file.com, file.COM, file.cpm and file.CPM
@ -218,7 +197,7 @@ void load_comfile(void)
}
if (!fp)
{
fprintf(stderr,"%s: Cannot locate %s, %s.com, %s.COM, %s.cpm _or_ %s.CPM\r\n",
fprintf(stderr, "%s: Cannot locate %s, %s.com, %s.COM, %s.cpm _or_ %s.CPM\n",
progname, argv[1], argv[1], argv[1], argv[1], argv[1]);
zxcc_term();
zxcc_exit(1);
@ -233,16 +212,16 @@ void load_comfile(void)
}
fclose(fp);
/* read() can corrupt buffer area following data read if length
* of data read is less than buffer. Clean it up. */
memset(RAM + 0x0100 + com_len, 0, 0xFD00 - com_len);
Msg("Loaded %d bytes from %s\n", com_len, fname);
DBGMSGV("Loaded %d bytes from %s\n", com_len, fname);
}
unsigned int in() { return 0; }
unsigned int out() { return 0; }
/*
* xltname: Convert a unix filepath into a CP/M compatible drive:name form.
* The unix filename must be 8.3 or the CP/M code will reject it.
@ -273,7 +252,6 @@ int main(int ac, char **av)
char* pCmd, * str;
char* tmpenv;
argc = ac;
argv = av;
#ifdef __PACIFIC__ /* Pacific C doesn't support argv[0] */
@ -289,16 +267,13 @@ int main(int ac, char **av)
#ifdef DEBUG
fprintf(stderr, "\n\n");
Msg("Start of execution: ");
DBGMSG("Start of execution: ");
for (n = 0; n < argc; n++)
fprintf(stderr, " %s", argv[n]);
fprintf(stderr, "\n");
#endif
if (_isatty(STDIN_FILENO))
Msg("Using interactive console mode\n");
else
Msg("Using standard input/ouput mode\n");
term_init();
if (sizeof(int) > 8 || sizeof(byte) != 1 || sizeof(word) != 2)
{
@ -313,14 +288,6 @@ int main(int ac, char **av)
zxcc_exit(1);
}
#ifdef _WIN32
setmode(STDIN_FILENO, O_BINARY );
setmode(STDOUT_FILENO, O_BINARY );
#else
if (_isatty(STDIN_FILENO))
raw_init();
#endif
/* Parse arguments. An argument can be either:
* preceded by a '-', in which case it is copied in as-is, less the
@ -360,9 +327,9 @@ int main(int ac, char **av)
if ((tmpenv = getenv("INCDIR80")))
mkpath(incdir80, tmpenv, "");
Msg("BINDIR80=\"%s\"\n", bindir80);
Msg("LIBDIR80=\"%s\"\n", libdir80);
Msg("INCDIR80=\"%s\"\n", incdir80);
DBGMSGV("BINDIR80=\"%s\"\n", bindir80);
DBGMSGV("LIBDIR80=\"%s\"\n", libdir80);
DBGMSGV("INCDIR80=\"%s\"\n", incdir80);
xlt_map(0, bindir80); /* Establish the 3 fixed mappings */
xlt_map(1, libdir80);
@ -401,7 +368,7 @@ int main(int ac, char **av)
parse_to_fcb(str, 0x6C);
// This statement is very useful when creating a client like zxc or zxas
Msg("Command tail is \"%s\"\n", pCmd);
DBGMSGV("Command tail is \"%s\"\n", pCmd);
load_bios();
@ -462,10 +429,6 @@ int zxcc_term(void)
{
word n;
#ifndef _WIN32
deinit_raw();
#endif
//n = RAM[0x81]; /* Get the return code. This is Hi-Tech C */
//n = (n << 8) | RAM[0x80]; /* specific and fails with other COM files */
n = 0;
@ -476,13 +439,16 @@ int zxcc_term(void)
{ /* (my modified Hi-Tech C library uses this */
n = cpm_error; /* call) */
}
if (n < 256 || n == 0xFFFF)
{
Msg("Return code %d\n", n);
DBGMSGV("Return code %d\n", n);
else
n = 0;
term_reset();
return n;
}
else return 0;
}
/* helper function to build full path */
/* make sure that a / or \ is present at the end of path
@ -503,11 +469,11 @@ void raw_init(void)
{
struct termios tc_raw;
Msg("Enabling RAW Terminal IO\n");
DBGMSG("Enabling RAW Terminal IO\n");
if (tcgetattr(STDIN_FILENO, &tc_orig) == -1)
{
Msg("Failed to enable RAW Terminal IO - tcgetattr() failed\n");
DBGMSG("Failed to enable RAW Terminal IO - tcgetattr() failed\n");
zxcc_exit(1);;
}
@ -527,11 +493,11 @@ void raw_init(void)
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tc_raw) == -1)
{
Msg("Failed to enable RAW Terminal IO - tcsetattr() failed\n");
DBGMSG("Failed to enable RAW Terminal IO - tcsetattr() failed\n");
zxcc_exit(1);
}
Msg("Enabled RAW Terminal IO\n");
DBGMSG("Enabled RAW Terminal IO\n");
return;
}
@ -540,13 +506,39 @@ void deinit_raw(void)
{
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tc_orig) == -1)
{
Msg("Failed to disable RAW Terminal IO - tcsetattr() failed\n");
DBGMSG("Failed to disable RAW Terminal IO - tcsetattr() failed\n");
return;
}
Msg("Disabled RAW Terminal IO\n");
DBGMSG("Disabled RAW Terminal IO\n");
return;
}
#endif
void term_init(void)
{
#ifdef _WIN32
setmode(STDIN_FILENO, O_BINARY);
setmode(STDOUT_FILENO, O_BINARY);
#else
if (_isatty(STDIN_FILENO))
raw_init();
#endif
if (_isatty(STDIN_FILENO))
DBGMSG("Using interactive console mode\n");
else
DBGMSG("Using standard input/output mode\n");
return;
}
void term_reset(void)
{
#ifndef _WIN32
if (_isatty(STDIN_FILENO))
deinit_raw();
#endif
}

27
Tools/unix/zxcc/zxcc.h

@ -22,9 +22,15 @@
#endif
/* the default sub directories trailing / is required */
#ifdef _WIN32
#define BIN80 "bin80\\"
#define LIB80 "lib80\\"
#define INC80 "include80\\"
#else
#define BIN80 "bin80/"
#define LIB80 "lib80/"
#define INC80 "include80/"
#endif
#ifndef BINDIR80
#define BINDIR80 CPMDIR80 BIN80
@ -58,6 +64,7 @@ extern char incdir80[];
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#include <conio.h>
#define strcasecmp _stricmp
#ifndef STDIN_FILENO
#define STDIN_FILENO _fileno(stdin)
@ -90,11 +97,11 @@ extern char incdir80[];
#include "cpmgsx.h"
#endif
#include "cpmredir.h" /* BDOS disc simulation */
typedef unsigned char byte; /* Must be exactly 8 bits */
typedef unsigned short word; /* Must be exactly 16 bits */
#include "cpmredir.h" /* BDOS disc simulation */
/* Prototypes */
void ed_fe (byte *a, byte *b, byte *c, byte *d, byte *e, byte *f,
@ -106,12 +113,21 @@ void cpmbios(byte *a, byte *b, byte *c, byte *d, byte *e, byte *f,
void dump_regs(FILE *fp, byte a, byte b, byte c, byte d, byte e, byte f,
byte h, byte l, word pc, word ix, word iy);
void Msg(char *s, ...);
void DbgMsg(const char *file, int line, const char *func, char *s, ...);
int zxcc_term(void);
void zxcc_exit(int code);
byte cin(void);
void cout(byte);
int cstat(void);
void term_init(void);
void term_reset(void);
#ifdef DEBUG
#define DBGMSGV(s, ...) DbgMsg(__FILE__, __LINE__, __func__, s, __VA_ARGS__)
#define DBGMSG(s) DbgMsg(__FILE__, __LINE__, __func__, s)
#else
#define DBGMSGV(s, ...)
#define DBGMSG(s)
#endif
/* Global variables */
@ -123,4 +139,3 @@ extern byte RAM[65536]; /* The Z80's address space */
/* Z80 CPU emulation */
#include "z80.h"

6
Tools/unix/zxcc/zxdbdos.c

@ -10,7 +10,6 @@
properly.
*/
/* If a file could not be found on the default drive, try again on a "search"
drive (A: for .COM files, B: for .LIB and .OBJ files) */
@ -75,8 +74,6 @@ word x_fcb_open(byte *fcb, byte *dma)
return rv;
}
word x_fcb_stat(byte* fcb)
{
word rv = fcb_stat(fcb);
@ -92,6 +89,3 @@ word x_fcb_stat(byte *fcb)
}
return rv;
}

4
Tools/unix/zxcc/zxdbdos.h

@ -1,8 +1,4 @@
int fcbforce(byte* fcb, byte* odrv);
word x_fcb_open(byte* fcb, byte* dma);
word x_fcb_stat(byte* fcb);

BIN
Tools/zxcc/zxcc-src.zip

Binary file not shown.

BIN
Tools/zxcc/zxcc.exe

Binary file not shown.

BIN
Tools/zxcc/zxccdbg.exe

Binary file not shown.
Loading…
Cancel
Save