Skip to content

Commit

Permalink
New v1.8
Browse files Browse the repository at this point in the history
-Now .BIN files can created for disk loading (formerly, they could be used inside a .CAS file only).
-Updated README.md
-Fixed some minor cosmetic bugs.
  • Loading branch information
jose-morente committed Oct 15, 2023
1 parent beab698 commit d032c4f
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 53 deletions.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
BASBINIZER v1.5
BASBINIZER v1.8
===============

BASBINIZER is a suite of tools for native MSX-BASIC file manipulation. It is multiplatform and several builds have been provided (Windows, Linux, Mac and MSX).
Expand All @@ -16,14 +16,16 @@ Using BASBINIZER on your PC/Mac/Linux computer

Syntax:

basbinizer <inputfile> [-b <outputfile> [-c <CAS FILENAME>]] [-a <ASC filename>] [-r <ROM filename>] [--fix] [--quiet]
basbinizer <inputfile> [-i <BIN filename>] [-b <CAS filename> [-c <BLOAD "NAME">]] [-a <ASC filename>] [-r <ROM filename>] [--fix] [--quiet]

Where
<intputfile> is the path to an MSX-BASIC .BAS file in tokenized

<outputfile> is the resulting .CAS file.
<BIN filename> is the .BIN file (loadable from disk)

<CAS FILENAME> if the name of the BLOAD name (max. 6 characters)
<CAS filename> is the resulting .CAS file.

<BLOAD "NAME"> is the name of the "FOUND" file (max. 6 characters)

<ROM filename> is the name of the ROM file

Expand All @@ -36,7 +38,7 @@ Options:
--quiet suppress messages on screen (except for critical errors)


ROM files must be under 16384 bytes and the variable area must start beyond address #C000. The program will fail if it sets the variable area to any address under #C000 (e.g. by using a CLEAR statement).
ROM files must be under 16368 bytes and the variable area must start beyond address #C000. The program will fail if it sets the variable area to any address under #C000 (e.g. by using a CLEAR statement).

Example:

Expand All @@ -47,6 +49,8 @@ Example:
basbinizer NIBBLES.BAS -a NIBBLES.ASC -b NIBBLES.CAS -C NIBBLE --fix

basbinizer NIBBLES.BAS -b NIBBLES.CAS -C NIBBLE -r NIBBLES.ROM --quiet

basbinizer NIBBLES.BAS -i NIBBLES.BIN


Using BASBINIZER on your MSX computer
Expand Down
164 changes: 119 additions & 45 deletions src/cli/basbinizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,25 @@ SOFTWARE.

void title(void)
{
fprintf(options.stdoutf, "_/_/_/_/_/_/_/_/ Basbinizer v1.5 _/_/_/_/_/_/_/_/\n");
fprintf(options.stdoutf, "_/_/_/_/_/_/_/_/ Basbinizer v%s _/_/_/_/_/_/_/_/\n",VERSION);
fprintf(options.stdoutf, "_/_/_/_/_/_/_/_/ 2023 MSXWiki.org _/_/_/_/_/_/_/_/\n\n\n");
}
void usage(void)
{
fprintf(options.stdoutf, "Syntax:\n\n");
fprintf(options.stdoutf, "basbinizer <inputfile> [-b <outputfile> [-c <CAS FILENAME>]] [-a <ASC filename>] [-r <ROM filename>] [--fix] [--quiet]\n\n");
fprintf(options.stdoutf, "basbinizer <inputfile> [-i <BIN filename>] [-b <CAS filename> [-c <BLOAD \"NAME\">]] [-a <ASC filename>] [-r <ROM filename>] [--fix] [--quiet]\n\n");
fprintf(options.stdoutf, "Where\n");
fprintf(options.stdoutf, "\t<intputfile> is the path to an MSX-BASIC .BAS file in tokenized format\n");
fprintf(options.stdoutf, "\t<outputfile> is the resulting .CAS file.\n");
fprintf(options.stdoutf, "\t<CAS FILENAME> is the name of the BLOAD name (max. 6 characters)\n");
fprintf(options.stdoutf, "\t<BIN filename> is the .BIN file (loadable from disk)\n");
fprintf(options.stdoutf, "\t<CAS filename> is the resulting .CAS file.\n");
fprintf(options.stdoutf, "\t<BLOAD \"NAME\"> is the name of the \"FOUND\" file (max. 6 characters)\n");
fprintf(options.stdoutf, "\t<ROM filename> is the name of the ROM file\n");
fprintf(options.stdoutf, "\t<ASC filename> to generate an ASCII file from the tokenized BASIC. If not specified, the ASCII text is written to the standard output.\n\n");
fprintf(options.stdoutf, "Options:\n");
fprintf(options.stdoutf, "\t--fix\t\tFixes certain data errors found in the source .BAS file\n");
fprintf(options.stdoutf, "\t--quiet\t\t suppress messages on screen (except for critical errors\n\n");

fprintf(options.stdoutf, "ROM files must be under 16384 bytes and the variable area must start beyond address #C000. The program will fail if it sets the variable area to any address under #C000 (e.g. by using a CLEAR statement)\n\n");
fprintf(options.stdoutf, "ROM files must be under %d bytes and the variable area must start beyond address #C000. The program will fail if it sets the variable area to any address under #C000 (e.g. by using a CLEAR statement)\n\n", MAX_ROM_SIZE);

fprintf(options.stdoutf, "Example:\n\tbasbinizer STARS.BAS -b STARS.CAS -c STARS\n\n\n");
}
Expand All @@ -53,7 +54,7 @@ bool process_params(int argc, char **argv, options_t *opt)
*/
opt->infile = NULL;
opt->infile_s = 0;
opt->outfile = NULL;
opt->casfile = NULL;
opt->ascfile = NULL;
opt->romfile = NULL;
memset(opt->casname, ' ', CAS_NAME_LEN);
Expand Down Expand Up @@ -100,52 +101,59 @@ bool process_params(int argc, char **argv, options_t *opt)
int i = 2;
while (i < argc)
{
if ((!strcmp(argv[i], "-b")) && (i < (argc - 1)))
if ((!strcmp(argv[i], "-i")) && (i < (argc - 1)))
{
opt->outfile = argv[++i];
opt->binfile = argv[++i];
}
else
{
if ((!strcmp(argv[i], "-c")) && (i < (argc - 1)))
if ((!strcmp(argv[i], "-b")) && (i < (argc - 1)))
{
int name_len = strlen(argv[++i]);
memcpy(opt->casname, argv[i], name_len > CAS_NAME_LEN ? CAS_NAME_LEN : name_len);
opt->casfile = argv[++i];
}
else
{
if (!strcmp(argv[i], "--fix"))
if ((!strcmp(argv[i], "-c")) && (i < (argc - 1)))
{
opt->fix = true;
int name_len = strlen(argv[++i]);
memcpy(opt->casname, argv[i], name_len > CAS_NAME_LEN ? CAS_NAME_LEN : name_len);
}
else
{
if (!strcmp(argv[i], "--quiet"))
if (!strcmp(argv[i], "--fix"))
{
opt->quiet = true;
#ifdef _WIN32
opt->stdoutf = fopen("NUL", "wb");
#else
opt->stdoutf = fopen("/dev/null", "wb");
#endif
opt->fix = true;
}
else
{
if ((!strcmp(argv[i], "-a")) && (i < (argc - 1)))
if (!strcmp(argv[i], "--quiet"))
{
opt->ascfile = argv[++i];
opt->quiet = true;
#ifdef _WIN32
opt->stdoutf = fopen("NUL", "wb");
#else
opt->stdoutf = fopen("/dev/null", "wb");
#endif
}
else
{
if ((!strcmp(argv[i], "-r")) && (i < (argc - 1)))
if ((!strcmp(argv[i], "-a")) && (i < (argc - 1)))
{
if (opt->infile_s <= MAX_ROM_SIZE)
{
opt->romfile = argv[++i];
}
else
opt->ascfile = argv[++i];
}
else
{
if ((!strcmp(argv[i], "-r")) && (i < (argc - 1)))
{
strcpy(opt->valerror, "BASIC program is too big to be fitted in a ROM.\n");
return (false);
if (opt->infile_s <= MAX_ROM_SIZE)
{
opt->romfile = argv[++i];
}
else
{
strcpy(opt->valerror, "BASIC program is too big to be fitted in a ROM.\n");
return (false);
}
}
}
}
Expand Down Expand Up @@ -230,9 +238,20 @@ int main(int argc, char **argv)
/*
Write .BIN file if requested
*/
if (options.outfile)
if (options.binfile)
{
if (!write_bin(inbuf, options.infile_s, options.outfile))
if (!write_bin(inbuf, options.infile_s, options.binfile))
{
return (1);
}
}

/*
Write .CAS file if requested
*/
if (options.casfile)
{
if (!write_cas(inbuf, options.infile_s, options.casfile))
{
return (1);
}
Expand Down Expand Up @@ -268,44 +287,99 @@ bool write_bin(byte *buffer, off_t buf_size, char *binf)
{

/*
Write file size into binary loader data (loader_data is a global array)
Write file size into binary loader data (bin_loader_data is a global array)
and BSAVE data on BIN header
*/
bin_loader_data[BIN_PATCH_POS] = (byte)((0x8000 + buf_size) & 0xff);
bin_loader_data[BIN_PATCH_POS + 1] = (byte)((0x8000 + buf_size) >> 8);

BIN_header[3] = (byte)((0x8000 + buf_size + BIN_LOADER_SIZE - 1) & 0xff);
BIN_header[4] = (byte)((0x8000 + buf_size + BIN_LOADER_SIZE - 1) >> 8);

BIN_header[5] = (byte)((0x8000 + buf_size) & 0xff);
BIN_header[6] = (byte)((0x8000 + buf_size) >> 8);

/*
Get memory for the buffer
*/
byte *bin_buffer = malloc(sizeof(BIN_header) + buf_size + BIN_LOADER_SIZE);

if (!bin_buffer)
{
fprintf(stderr, "Memory error trying to find %lld bytes free while writing .BIN File... exiting.\n\n", sizeof(BIN_header) + buf_size + BIN_LOADER_SIZE);

return (false);
}

/*
Copy data to the .BIN buffer
*/
memcpy(bin_buffer, BIN_header, 7);
memcpy(bin_buffer + 7, buffer, buf_size);
memcpy(bin_buffer + 7 + buf_size, bin_loader_data, BIN_LOADER_SIZE);

/*
finally, open output file and write data
*/
FILE *fo = fopen(binf, "wb");
if (!fo)
{
fprintf(stderr, "Error opening .BIN file %s.\n", binf);
return (false);
}

if (fwrite(bin_buffer, 1, sizeof(BIN_header) + buf_size + BIN_LOADER_SIZE, fo) != (sizeof(BIN_header) + buf_size + BIN_LOADER_SIZE))
{
fprintf(stderr, "Error writing .BIN file %s.\n", binf);
}

fclose(fo);
free(bin_buffer);

return (true);
}
bool write_cas(byte *buffer, off_t buf_size, char *casf)
{

/*
Write file size into cas binary loader data (cas_loader_data is a global array)
*/
loader_data[PATCH_POS] = (byte)(buf_size & 0xff);
loader_data[PATCH_POS + 1] = (byte)((buf_size & 0xff00) >> 8);
cas_loader_data[PATCH_POS] = (byte)(buf_size & 0xff);
cas_loader_data[PATCH_POS + 1] = (byte)((buf_size & 0xff00) >> 8);

memcpy(loader_data + PATCH_NAME_POS, options.casname, CAS_NAME_LEN);
memcpy(cas_loader_data + PATCH_NAME_POS, options.casname, CAS_NAME_LEN);

/*
Get memory for the buffer
*/
byte *cas_buffer = malloc(LOADER_SIZE + buf_size);
byte *cas_buffer = malloc(CAS_LOADER_SIZE + buf_size);

if (!cas_buffer)
{
fprintf(stderr, "Memory error trying to find %lld bytes free while writing CAS file... exiting.\n\n", LOADER_SIZE + buf_size);
fprintf(stderr, "Memory error trying to find %lld bytes free while writing CAS file... exiting.\n\n", CAS_LOADER_SIZE + buf_size);

return (false);
}

/*
copy data and concat .BAS file
*/
memcpy(cas_buffer, loader_data, LOADER_SIZE);
memcpy(cas_buffer + LOADER_SIZE, buffer, buf_size);
memcpy(cas_buffer, cas_loader_data, CAS_LOADER_SIZE);
memcpy(cas_buffer + CAS_LOADER_SIZE, buffer, buf_size);

/*
finally, open output file and write data
*/
FILE *fo = fopen(binf, "wb");
FILE *fo = fopen(casf, "wb");
if (!fo)
{
fprintf(stderr, "Error opening .CAS file %s.\n", binf);
fprintf(stderr, "Error opening .CAS file %s.\n", casf);
return (false);
}

if (fwrite(cas_buffer, 1, LOADER_SIZE + buf_size, fo) != (LOADER_SIZE + buf_size))
if (fwrite(cas_buffer, 1, CAS_LOADER_SIZE + buf_size, fo) != (CAS_LOADER_SIZE + buf_size))
{
fprintf(stderr, "Error writing .CAS file %s.\n", binf);
fprintf(stderr, "Error writing .CAS file %s.\n", casf);
}

fclose(fo);
Expand All @@ -322,7 +396,7 @@ bool write_rom(byte *inbuf, off_t buf_size, char *romfile)

if (!rom_buffer)
{
fprintf(stderr, "Memory error trying to find %lld bytes free while writing ROM file... exiting.\n\n", LOADER_SIZE + buf_size);
fprintf(stderr, "Memory error trying to find %d bytes free while writing ROM file... exiting.\n\n", ROM_SIZE);

return (false);
}
Expand Down
23 changes: 20 additions & 3 deletions src/cli/basbinizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ typedef long long int off_t;
typedef struct _stat st_stat;
#endif

#define LOADER_SIZE 174
#define VERSION "1.8"
#define BIN_LOADER_SIZE 50
#define CAS_LOADER_SIZE 174
#define BIN_PATCH_POS 10
#define PATCH_POS 51
#define PATCH_NAME_POS 0x12
#define CAS_NAME_LEN 6
Expand All @@ -45,14 +48,26 @@ typedef struct _stat st_stat;
#define MAX_ROM_SIZE 16384 - 0x10
#define BASE_BIN 0x8000
#define BASE_ROM 0x8010
#define REL_PROG 0xf975

typedef uint8_t byte;

byte ROM_header[16] = {
0x41, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
byte loader_data[LOADER_SIZE] = {
byte BIN_header[7] = {
0xfe, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00
};
byte bin_loader_data[BIN_LOADER_SIZE] = {
0xF3, 0x3E, 0xC9, 0x32, 0x9A, 0xFD, 0x32, 0x9F, 0xFD, 0x21, 0x00, 0x00,
0x22, 0xC2, 0xF6, 0x21, 0x01, 0x80, 0x22, 0x76, 0xF6, 0x2B, 0x22, 0x48,
0xFC, 0x3E, 0x0F, 0x21, 0xE9, 0xF3, 0x77, 0x3E, 0x01, 0x23, 0x77, 0x23,
0x77, 0xCD, 0x62, 0x00, 0xCD, 0x6C, 0x00, 0xAF, 0x32, 0x00, 0x80, 0xC3,
0xAC, 0x73

};
byte cas_loader_data[CAS_LOADER_SIZE] = {
0x1F, 0xA6, 0xDE, 0xBA, 0xCC, 0x13, 0x7D, 0x74, 0xD0, 0xD0, 0xD0, 0xD0,
0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0x47, 0x41, 0x4D, 0x45, 0x20, 0x20,
0x1F, 0xA6, 0xDE, 0xBA, 0xCC, 0x13, 0x7D, 0x74, 0x75, 0xF9, 0xF4, 0xF9,
Expand Down Expand Up @@ -80,7 +95,8 @@ typedef struct options
bool quiet;
char *infile;
off_t infile_s;
char *outfile;
char *casfile;
char *binfile;
char *ascfile;
char *romfile;
byte casname[CAS_NAME_LEN];
Expand Down Expand Up @@ -117,6 +133,7 @@ int get_colon(byte *buffer, int pos, FILE *output);
int get_string(byte *buffer, int pos, FILE *output);
bool process_bas(byte *buffer, off_t file_size, uint16_t base_addr, bool force_quiet);
bool write_bin(byte *buffer, off_t buf_size, char *binf);
bool write_cas(byte *buffer, off_t buf_size, char *casf);
bool write_rom(byte *inbuf, off_t buf_size, char *romfile);
bool process_opt(int argc, char **argv, options_t *opt);

Expand Down
Loading

0 comments on commit d032c4f

Please sign in to comment.