/* */
/* */
/* */
-/* (C) 2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 2000-2009, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
+#include <ctype.h>
#include <errno.h>
+/* common */
+#include "addrsize.h"
+#include "cpu.h"
+#include "version.h"
+
/* da65 */
#include "code.h"
#include "error.h"
static FILE* F = 0; /* Output stream */
static unsigned Col = 1; /* Current column */
+static unsigned Line = 0; /* Current line on page */
+static unsigned Page = 1; /* Current output page */
+
/*****************************************************************************/
+static void PageHeader (void)
+/* Print a page header */
+{
+ fprintf (F,
+ "; da65 V%s - (C) Copyright 2000-2009, Ullrich von Bassewitz\n"
+ "; Created: %s\n"
+ "; Input file: %s\n"
+ "; Page: %u\n\n",
+ GetVersionAsString (),
+ Now,
+ InFile,
+ Page);
+}
+
+
+
void OpenOutput (const char* Name)
/* Open the given file for output */
{
- /* Open the output file */
- F = fopen (Name, "w");
- if (F == 0) {
- Error ("Cannot open `%s': %s", Name, strerror (errno));
+ /* If we have a name given, open the output file, otherwise use stdout */
+ if (Name != 0) {
+ F = fopen (Name, "w");
+ if (F == 0) {
+ Error ("Cannot open `%s': %s", Name, strerror (errno));
+ }
+ } else {
+ F = stdout;
}
+
+ /* Output the header and initialize stuff */
+ PageHeader ();
+ Line = 5;
+ Col = 1;
}
void CloseOutput (void)
/* Close the output file */
{
- if (fclose (F) != 0) {
+ if (F != stdout && fclose (F) != 0) {
Error ("Error closing output file: %s", strerror (errno));
}
}
void Output (const char* Format, ...)
/* Write to the output file */
{
- if (Pass > 1) {
+ if (Pass == PassCount) {
va_list ap;
va_start (ap, Format);
Col += vfprintf (F, Format, ap);
void Indent (unsigned N)
/* Make sure the current line column is at position N (zero based) */
{
- if (Pass > 1) {
+ if (Pass == PassCount) {
while (Col < N) {
fputc (' ', F);
++Col;
void LineFeed (void)
/* Add a linefeed to the output file */
{
- if (Pass > 1) {
+ if (Pass == PassCount) {
fputc ('\n', F);
- Col = 1;
+ if (PageLength > 0 && ++Line >= PageLength) {
+ if (FormFeeds) {
+ fputc ('\f', F);
+ }
+ ++Page;
+ PageHeader ();
+ Line = 5;
+ }
+ Col = 1;
}
}
/* Define a label with the given name */
{
Output ("%s:", Name);
+ /* If the label is longer than the configured maximum, or if it runs into
+ * the opcode column, start a new line.
+ */
+ if (Col > LBreak+2 || Col > MCol) {
+ LineFeed ();
+ }
+}
+
+
+
+void DefForward (const char* Name, const char* Comment, unsigned Offs)
+/* Define a label as "* + x", where x is the offset relative to the
+ * current PC.
+ */
+{
+ if (Pass == PassCount) {
+ /* Flush existing output if necessary */
+ if (Col > 1) {
+ LineFeed ();
+ }
+
+ /* Output the forward definition */
+ Output ("%s", Name);
+ Indent (ACol);
+ if (UseHexOffs) {
+ Output (":= * + $%04X", Offs);
+ } else {
+ Output (":= * + %u", Offs);
+ }
+ if (Comment) {
+ Indent (CCol);
+ Output ("; %s", Comment);
+ }
+ LineFeed ();
+ }
+}
+
+
+
+void DefConst (const char* Name, const char* Comment, unsigned Addr)
+/* Define an address constant */
+{
+ if (Pass == PassCount) {
+ Output ("%s", Name);
+ Indent (ACol);
+ Output (":= $%04X", Addr);
+ if (Comment) {
+ Indent (CCol);
+ Output ("; %s", Comment);
+ }
+ LineFeed ();
+ }
+}
+
+
+
+void StartSegment (const char* Name, unsigned AddrSize)
+/* Start a segment */
+{
+ if (Pass == PassCount) {
+ Output (".segment");
+ Indent (ACol);
+ if (AddrSize == ADDR_SIZE_DEFAULT) {
+ Output ("\"%s\"", Name);
+ } else {
+ Output ("\"%s\": %s", Name, AddrSizeToStr (AddrSize));
+ }
+ LineFeed ();
+ }
+}
+
+
+
+void DataByteLine (unsigned ByteCount)
+/* Output a line with bytes */
+{
+ unsigned I;
+
+ Indent (MCol);
+ Output (".byte");
+ Indent (ACol);
+ for (I = 0; I < ByteCount; ++I) {
+ if (I > 0) {
+ Output (",$%02X", CodeBuf[PC+I]);
+ } else {
+ Output ("$%02X", CodeBuf[PC+I]);
+ }
+ }
+ LineComment (PC, ByteCount);
LineFeed ();
}
-void OneDataByte (void)
-/* Output a .byte line with the current code byte */
+void DataDByteLine (unsigned ByteCount)
+/* Output a line with dbytes */
{
- unsigned char B = GetCodeByte ();
+ unsigned I;
+
+ Indent (MCol);
+ Output (".dbyt");
+ Indent (ACol);
+ for (I = 0; I < ByteCount; I += 2) {
+ if (I > 0) {
+ Output (",$%04X", GetCodeDByte (PC+I));
+ } else {
+ Output ("$%04X", GetCodeDByte (PC+I));
+ }
+ }
+ LineComment (PC, ByteCount);
+ LineFeed ();
+}
- if (Pass > 1) {
- Indent (MIndent);
- Output (".byte");
- Indent (AIndent);
- Output ("$%02X", B);
- LineFeed ();
+
+
+void DataWordLine (unsigned ByteCount)
+/* Output a line with words */
+{
+ unsigned I;
+
+ Indent (MCol);
+ Output (".word");
+ Indent (ACol);
+ for (I = 0; I < ByteCount; I += 2) {
+ if (I > 0) {
+ Output (",$%04X", GetCodeWord (PC+I));
+ } else {
+ Output ("$%04X", GetCodeWord (PC+I));
+ }
+ }
+ LineComment (PC, ByteCount);
+ LineFeed ();
+}
+
+
+
+void DataDWordLine (unsigned ByteCount)
+/* Output a line with dwords */
+{
+ unsigned I;
+
+ Indent (MCol);
+ Output (".dword");
+ Indent (ACol);
+ for (I = 0; I < ByteCount; I += 4) {
+ if (I > 0) {
+ Output (",$%08lX", GetCodeDWord (PC+I));
+ } else {
+ Output ("$%08lX", GetCodeDWord (PC+I));
+ }
}
+ LineComment (PC, ByteCount);
+ LineFeed ();
}
void SeparatorLine (void)
/* Print a separator line */
{
- Output ("; -------------------------------------------------------------------------");
+ if (Pass == PassCount && Comments >= 1) {
+ Output ("; ----------------------------------------------------------------------------");
+ LineFeed ();
+ }
+}
+
+
+
+void UserComment (const char* Comment)
+/* Output a comment line */
+{
+ Output ("; %s", Comment);
+ LineFeed ();
+}
+
+
+
+void LineComment (unsigned PC, unsigned Count)
+/* Add a line comment with the PC and data bytes */
+{
+ unsigned I;
+
+ if (Pass == PassCount && Comments >= 2) {
+ Indent (CCol);
+ Output ("; %04X", PC);
+ if (Comments >= 3) {
+ for (I = 0; I < Count; ++I) {
+ Output (" %02X", CodeBuf [PC+I]);
+ }
+ if (Comments >= 4) {
+ Indent (TCol);
+ for (I = 0; I < Count; ++I) {
+ unsigned char C = CodeBuf [PC+I];
+ if (!isprint (C)) {
+ C = '.';
+ }
+ Output ("%c", C);
+ }
+ }
+ }
+ }
+}
+
+
+
+void OutputSettings (void)
+/* Output CPU and other settings */
+{
+ LineFeed ();
+ Indent (MCol);
+ Output (".setcpu");
+ Indent (ACol);
+ Output ("\"%s\"", CPUNames[CPU]);
+ LineFeed ();
LineFeed ();
}
-