kolibrios/programs/emulator/dgen-sdl-1.33/dz80/dz80.c

287 lines
6.2 KiB
C
Raw Normal View History

/*
dZ80 - Z80 Disassembler v2.0
Written by Mark Incley, 1st November, 1996 (v1.0)
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include "types.h"
#include "dissz80.h"
#include "dz80.h"
char reqLayoutNumberPrefix[D_CUSTOMSTRING_MAXLEN], reqLayoutNumberSuffix[D_CUSTOMSTRING_MAXLEN];
int disRadix, showVersion;
static DWORD bytesLoaded;
static void ProgressUpdate(DISZ80 *d);
/* Not a great big table at the moment :) */
DISFILE FileExtList[]=
{
{"sna", 27, 16384}, /* .SNA - Spectrum Snapshots */
{NULL, 0, 0}
};
int main(int argc, char* argv[])
{
char buf[256];
int err, startArgc;
DISZ80 *d;
sprintf(buf, "dZ80 %s, Copyright 1996-2002 by Mark Incley.\n", dZ80_GetVersionString());
PrintToConsole(buf);
d = malloc(sizeof(DISZ80));
if (d == NULL)
{
PrintToErrOut("Couldn't allocate DISZ80 structure");
exit(1);
}
/* Set up our DISZ80 structure */
memset(d, 0, sizeof(DISZ80));
d->fnOutputMessage = PrintToConsole;
d->fnErrorMessage = PrintToErrOut;
d->fnProgressCallback = ProgressUpdate;
d->cpuType = DCPU_Z80;
d->flags = DISFLAG_OPCODEDUMP | DISFLAG_ADDRDUMP | DISFLAG_USELABELADDRS;
dZ80_SetDefaultOptions(d);
showVersion = FALSE;
d->start = 0;
d->end = 65535;
disRadix = DRADIX_DEFAULT;
/* Allocate the opcode map so that the config.file may modify it */
dZ80_AllocateOpMap(d);
/* Have we passed the special case switch? */
startArgc = 1;
if (argc > 1)
{
if (!strcmp(argv[1], OMITCONFIGSWITCH))
startArgc++;
}
/* Load the config file dZ80.ini */
if (startArgc == 1)
{
err = dZ80_LoadConfiguration(d, NULL);
if (err != DERR_NONE && err != DERR_SCRIPTING_NA)
{
sprintf(buf, "Error loading %s: %s", CONFIGFILENAME, dZ80_GetErrorText(err));
PrintToConsole(buf);
exit(1);
}
}
/* Parse the command line, overriding any config file settings */
if (ParseCmdLine(d, startArgc, argc, argv))
exit(1);
if (showVersion)
{
ShowVersionInfo();
exit(0);
}
if (d->srcFileName[0] == 0)
{
ShowUsage();
exit(0);
}
/*
Note if we've specified a radix, we set it and then separately copy the prefix and suffixes
across, as they will have been clobbered by dZ80_SetRadix
*/
if (d->layoutRadix != disRadix)
dZ80_SetRadix(d, disRadix);
if (d->parametersModified & DPM_NUMPREFIX)
strcpy(d->layoutNumberPrefix, reqLayoutNumberPrefix);
if (d->parametersModified & DPM_NUMSUFFIX)
strcpy(d->layoutNumberSuffix, reqLayoutNumberSuffix);
ScanFilenameForPresets(d);
ParseFilenames(d);
err = dZ80_LoadZ80File(d, &bytesLoaded);
if (err)
exit(err);
if (bytesLoaded == 0)
{
dZ80_Error(d, "Cannot load a zero byte file.\n");
exit(1);
}
/* Make sure we've got sensible start and end addresses */
if (d->start < d->fileStartAddr)
{
if (!(d->parametersModified & DPM_STARTADDR))
d->start = d->fileStartAddr;
}
if (d->end > (d->fileStartAddr + bytesLoaded))
{
if (!(d->parametersModified & DPM_ENDADDR))
d->end = d->fileStartAddr + (WORD)(bytesLoaded - 1);
}
/* ...and do the biz */
dZ80_Disassemble(d);
free(d->mem0Start);
free(d);
exit(0);
}
void ParseFilenames(DISZ80 *d)
{
char *extPtr;
/* If specified a reference filename, don't interfere */
if (d->refFileName[0])
return;
/* Are we going to need a reference filename ? */
if (d->flags & DISFLAG_ANYREF)
{
strcpy(d->refFileName, d->srcFileName);
/* Hardly, foolproof, but this will replace any extension with .REF */
extPtr = (char *)strrchr(d->refFileName, '.');
/* If there is a period, make sure it isn't a terminating one */
if (extPtr != NULL)
{
if (*extPtr+1)
{
strcpy(extPtr+1, "ref");
return;
}
}
else
{
strcat(d->refFileName, ".ref");
}
}
return;
}
void ScanFilenameForPresets(DISZ80 *d)
{
char *extPtr;
char fileExt[16], buf[128];
int i;
extPtr = strrchr(d->srcFileName, '.');
if (extPtr == NULL)
return; /* No extension, so no presets. */
strcpy(fileExt, (extPtr)+1);
dZ80_StringToLower(fileExt); /* Make lower case */
for (i=0; ; i++)
{
if (FileExtList[i].Extension == 0)
return;
if (!strcmp(fileExt, FileExtList[i].Extension) )
{
if (!(d->flags & DISFLAG_QUIET))
{
sprintf(buf, "Using presets for .%s file extension.\n", fileExt);
PrintToConsole(buf);
}
d->fileHeaderSize = FileExtList[i].FileHeaderSize;
d->fileStartAddr = FileExtList[i].BaseOffset;
return;
}
}
}
void PrintToErrOut(char *Str)
{
fwrite(Str, 1, strlen(Str), stderr);
fwrite("\n", 1, 1, stderr);
return;
}
void PrintToConsole(char *Str)
{
printf("%s\n", Str);
return;
}
/*
This function is frequently called by the disassembler module to allow its progress
to be displayed. It's used by the Windows version of dZ80 to implement a progress bar.
*/
static void ProgressUpdate(DISZ80 *d)
{
return;
}
void ShowVersionInfo(void)
{
char buf[256];
sprintf(buf, "dZ80 core %s, %s", dZ80_GetVersionString(), LUA_VERSION);
PrintToConsole(buf);
return;
}
void ShowUsage(void)
{
char buf[256];
sprintf(buf,
"Disassembles a Z80 binary file. E-mail: %s\n", DZ80_EMAIL);
PrintToConsole(buf);
PrintToConsole("DZ80 [!] [switches] infile [outfile]\n"
"\n"
" ! Prevents dZ80 from automatically loading the configuration file.\n"
" -h=nn Skips past the first nn bytes of the input file.\n"
" -m=nn Specifies whereabouts in Z80 memory the file starts.\n"
" -s=nn Specifies the address to start disassembling from.\n"
" -e=nn Specifies the ending disassembly address.\n"
" -r=file Specify the name for the reference file. Used with -xa -xn -xo -xi.\n"
" -xi Create reference of input ports.\n"
" -xo Create reference of output ports.\n"
" -xa Create reference of addresses.\n"
" -xn Create reference of indirect addresses.\n"
" -k=script Use the specified script file.\n"
" -l Create a labelled (assembleable) output file.\n"
" -z=cpu Set the CPU type to Z80GB, Z80 (default) or Z180.\n"
);
sprintf(buf,
"Note that this is only a partial list of switches. You can use the %s\n"
"configuration file to control dz80. Please read the dz80.txt file for details.", CONFIGFILENAME);
PrintToConsole(buf);
return;
}