changeset 0:4410c9c7750d

Initial import.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 24 Feb 2015 18:53:52 +0200
parents
children cfcae2ef1c2b
files INSTALL Makefile dump.c dxa.1 label.c main.c opcodes.h options.h proto.h scan.c structures.h table.c vector.c
diffstat 13 files changed, 3750 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/INSTALL	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,17 @@
+Installation for dxa
+--------------------
+
+dxa should build out of the box with any even vaguely recent version of gcc.
+You might need to do some tweakage for non-Unix systems or cc. I have tested
+it on AIX, NetBSD and Mac OS X/Darwin. -- Cameron Kaiser
+
+1. Uncomment LONG_OPTIONS in options.h if you have getopts_long() and want
+   long options (--example). This is purely optional.
+2. Edit the Makefile and make sure your compiler and CFLAGS make sense. The
+   default works for most people.
+3. "make"
+4. Documentation in man format is in dxa.1.
+
+Please keep in mind this is still considered "alpha" software and there may
+be bugs, which is why it is not part of the official xa distribution yet.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,34 @@
+# dxa makefile
+# marko's originally, hacked up by cameron
+
+TARGET = dxa
+OBJECTS = scan.o vector.o dump.o table.o label.o main.o
+VERSION = 0.1.3
+
+# choose the compiler and flags
+
+CC = gcc
+CFLAGS = -Wall -Wmissing-prototypes -O6
+#CFLAGS = -Wall -Wmissing-prototypes -ggdb
+
+#CC = cc
+#CFLAGS = -O
+#CFLAGS = -O2
+
+all: $(TARGET)
+
+$(TARGET) : $(OBJECTS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJECTS)
+
+scan.o : structures.h proto.h options.h opcodes.h
+vector.o : structures.h proto.h options.h
+dump.o : structures.h proto.h options.h opcodes.h
+table.o : structures.h proto.h
+label.o : structures.h proto.h
+main.o : structures.h proto.h options.h opcodes.h
+
+clean:
+	rm -f $(OBJECTS) $(TARGET) core
+
+dist: clean
+	cd ..;tar cvf dxa-$(VERSION).tar dxa-$(VERSION);gzip dxa-$(VERSION).tar
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dump.c	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,324 @@
+/*\
+ *  dxa v0.1.3 -- symbolic 65xx disassembler
+ *
+ *  Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *  Changes for dxa (C) 2004, 2006 Cameron Kaiser
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Marko does not maintain dxa, so questions specific to dxa should be
+ *  sent to me at ckaiser@floodgap.com . Otherwise,
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+#define _DUMP_C_
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "proto.h"
+#include "options.h"
+#include "opcodes.h"
+
+#ifndef __STDC__
+void
+Dump ()
+#else
+void Dump (void)
+#endif
+{
+  ADDR_T address, addr;
+  unsigned counter, size, maxwidth;
+  char *lineprefix, *lineinfix;
+  table *entry;
+  opcodes *instr;
+
+  if (fVerbose)
+    fprintf (stderr, "%s: Dumping the source code.\n", prog);
+
+  /* determine the maximum amount of bytes dumped per line */
+
+  maxwidth = listwidth < 2 ? 2 : listwidth;
+
+  for (counter = 0; counter < 256; counter++)
+    if (maxwidth < sizes[opset[counter].admode])
+      maxwidth = sizes[opset[counter].admode];
+
+  /* create prefix string for lines without address information */
+  switch (Options & M_ADDRESSES) {
+  case O_ADR_ADRPFIX:
+    counter = 5;
+    break;
+
+  case O_ADR_ADR_DMP:
+    counter = 5 + 3 * maxwidth;
+    break;
+
+  default:
+    counter = 0;
+  }
+
+  lineprefix = malloc (counter + 1);
+
+  if (counter >= 5) {
+    lineinfix = lineprefix + 5;
+
+    for (lineprefix[counter] = 0; counter--; lineprefix[counter] = ' ');
+  }
+  else {
+    *lineprefix = 0;
+    lineinfix = lineprefix;
+  }
+
+  /* print the label definitions */
+
+  for (address = EndAddress < StartAddress ? EndAddress : 0;
+       address != StartAddress; address++)
+    if (IsLabeled (address))
+      fprintf (stdout, "%s%s = $%x\n", lineprefix, Label (address, abso),
+	address);
+
+  if (EndAddress >= StartAddress)
+    for (address = EndAddress; address; address++)
+      if (IsLabeled (address))
+        fprintf (stdout, "%s%s = $%x\n", lineprefix, Label (address, abso),
+		address);
+
+  /* dump the program */
+
+  if(Options & B_SA_WORD)
+	fprintf(stdout, "%s\t.word $%04x", lineprefix, StartAddress);
+  fprintf (stdout, "\n%s\t* = $%04x\n\n", lineprefix, StartAddress);
+
+  for (address = StartAddress; (ADDR_T)(address - StartAddress) <
+       (ADDR_T)(EndAddress - StartAddress); address += size)
+    if (GetMemType (address) == MEM_INSTRUCTION) {
+      if (IsLabeled (address)) {
+	if (Options & M_ADDRESSES)
+	  fprintf (stdout, "%04x %s%s:\n", address,
+                   lineinfix, Label (address, abso));
+	else {
+	  fprintf (stdout, "%s", Label (address, abso));
+		if (Options & B_LABCOL)
+			fprintf(stdout, ":\n");
+	}
+      }
+
+      instr = &opset[Memory[address]];
+      size = sizes[instr->admode];
+
+      for (counter = 1; counter < size; counter++) {
+        if (IsLabeled (address + counter)) {
+	  if (Options & M_ADDRESSES)
+	    fprintf (stdout, "\t%04x %s%s = * + %u\n",
+                     (ADDR_T)(address + counter),
+		     lineinfix, Label (address + counter, abso), counter);
+	  else
+	    fprintf (stdout, "\t%s = * + %u\n",
+		     Label (address + counter, abso), counter);
+	}
+
+        if (FindNextEntry (NULL, address, ~0, WRN_INSTR_WRITTEN_TO))
+          fprintf (stdout, "%s; Instruction opcode accessed.\n", lineprefix);
+
+        entry = NULL;
+
+        while ((entry = FindNextEntry (entry, address + counter, 0, 0)))
+          switch (entry->type) {
+          case WRN_PARAM_WRITTEN_TO:
+            fprintf (stdout, "%s; Instruction parameter accessed.\n",
+		     lineprefix);
+            break;
+
+          case WRN_PARAM_JUMPED_TO:
+            fprintf (stdout, "%s; Instruction parameter jumped to.\n",
+		     lineprefix);
+            break;
+          }
+      }
+
+      switch (Options & M_ADDRESSES) {
+      case O_ADR_ADRPFIX:
+	fprintf (stdout, "%04x ", address);
+	break;
+
+      case O_ADR_ADR_DMP:
+	fprintf (stdout, "%04x ", address);
+
+	for (counter = 0; counter < size; counter++)
+	  fprintf (stdout, "%02x ", Memory[(ADDR_T)(address + counter)]);
+
+	fputs (lineinfix + 3 * counter, stdout);
+      }
+
+      fputs ("\t", stdout);
+
+      switch (instr->admode) {
+      case accu:
+      case impl:
+        fprintf (stdout, "%s%s\n", mne[instr->mnemonic],
+                 postfix[instr->admode]);
+        break;
+      case imm:
+        addr = Memory[(ADDR_T)(address + 1)];
+        fprintf (stdout, "%s #$%02x\n", mne[instr->mnemonic], addr);
+        break;
+      case abso:
+      case absx:
+      case absy:
+      case iabs:
+      case iabsx:
+        addr = Memory[(ADDR_T)(address + 1)] |
+          (Memory[(ADDR_T)(address + 2)] << 8);
+          /* Fix to ensure 16-bit addresses to zero-page are maintained as 16-bit */
+          fprintf (stdout, "%s %s%s%s%s\n", mne[instr->mnemonic],
+		prefix[instr->admode],
+                   ((addr < 256 && instr->mnemonic != S_JMP &&
+			instr->mnemonic != S_JSR) ? "!" : ""),
+                   Label (addr, abso),postfix[instr->admode]);
+        break;
+      case zp:
+      case zpx:
+      case zpy:
+      case ind:
+      case indx:
+      case indy:
+        addr = Memory[(ADDR_T)(address + 1)];
+        fprintf (stdout, "%s %s%s%s\n", mne[instr->mnemonic],
+                 prefix[instr->admode], Label (addr, zp),
+                 postfix[instr->admode]);
+        break;
+      case rel:
+        addr = (int)(char)Memory[(ADDR_T)(address + 1)];
+	/* addr -= (addr > 127) ? 256 : 0; BUGFIX: sign extend already done */
+/*fprintf(stderr, "%d %d %d\n", address, size, addr);*/
+        addr += address + size;
+        fprintf (stdout, "%s %s%s%s\n", mne[instr->mnemonic],
+                 prefix[instr->admode], Label (addr, abso),
+                 postfix[instr->admode]);
+        break;
+      case zrel: /* BBR0, etc. 65C02 instructions */
+        addr = (int)(char)Memory[(ADDR_T)(address + 2)];
+	/* addr -= (addr > 127) ? 256 : 0; BUGFIX: sign extend already done */
+        addr += address + size;
+        fprintf (stdout, "%s %s, %s\n", mne[instr->mnemonic],
+                Label (Memory[(ADDR_T)(address + 1)], abso),
+		Label (addr, abso));
+        break;
+      }
+    }
+    else if (address != (addr = WordTableEnd (address))) { /* word table */
+      for (size = (ADDR_T)(addr - address); size;
+	   address += (counter = size > (maxwidth & ~1) ?
+                       (maxwidth & ~1) : size), size -= counter) {
+	if (IsLabeled (address)) {
+	  if (Options & M_ADDRESSES)
+	    fprintf (stdout, "%04x %s%s:\n", address, lineinfix,
+                     Label (address, abso));
+	  else
+	    fprintf (stdout, "%s ", Label (address, abso));
+	}
+	for (counter = size > (maxwidth & ~1) ? (maxwidth & ~1) : size,
+	     addr = address + 1; --counter; addr++)
+	  if (IsLabeled (addr)) {
+	    if (Options & M_ADDRESSES)
+	      fprintf (stdout, "%04x %s%s = * + %u\n", addr, lineinfix,
+		       Label (addr, abso), (ADDR_T)(addr - address));
+	    else
+	      fprintf (stdout, "\t%s = * + %u\n", Label (addr, abso),
+		       (ADDR_T)(addr - address));
+	  }
+
+	if (Options & M_ADDRESSES)
+	  fprintf (stdout, "%04x ", address);
+
+	if ((Options & M_ADDRESSES) == O_ADR_ADR_DMP) {
+	  for (counter = size > (maxwidth & ~1) ? (maxwidth & ~1) : size,
+	       addr = address; counter--; addr++) {
+	    fprintf (stdout, "%02x ", Memory[addr]);
+	  }
+	  fputs (lineinfix + 3 * (size > (maxwidth & ~1) ?
+				  (maxwidth & ~1) : size), stdout);
+	}
+
+	fprintf (stdout, "  .word %s",
+		 Label (Memory[address] |
+                 (Memory[(ADDR_T)(address + 1)] << 8), abso));
+
+	for (counter = size > (maxwidth & ~1) ? (maxwidth & ~1) : size,
+	     addr = address + 2; counter -= 2; addr += 2)
+	  fprintf (stdout, ",%s",
+		   Label (Memory[addr] | (Memory[(ADDR_T)(addr + 1)] << 8),
+			abso));
+			
+
+	fputc ('\n', stdout);
+      }
+    }
+    else { /* data block */
+      for (size = 1; size < maxwidth; size++) { /* determine the size */
+	addr = address + size; 
+
+	if (GetMemType (addr) == MEM_INSTRUCTION ||
+	    addr != WordTableEnd (addr))
+	  break;
+      }
+
+      if (IsLabeled (address)) {
+	if (Options & M_ADDRESSES)
+	  fprintf (stdout, "%04x %s%s:\n", address, lineinfix,
+		   Label (address, abso));
+	else
+	  fprintf (stdout, "%s ", Label (address, abso));
+      }
+
+      for (counter = size, addr = address + 1; --counter; addr++)
+        if (IsLabeled (addr)) {
+	  if (Options & M_ADDRESSES)
+	    fprintf (stdout, "%04x %s%s = * + %u\n", addr, lineinfix,
+		     Label (addr, abso), (ADDR_T)(addr - address));
+	  else
+	    fprintf (stdout, "\t%s = * + %u\n", Label (addr, abso),
+		     (ADDR_T)(addr - address));
+        }
+
+      if (Options & M_ADDRESSES)
+	fprintf (stdout, "%04x ", address);
+
+      if ((Options & M_ADDRESSES) == O_ADR_ADR_DMP) {
+	for (counter = size, addr = address; counter--; addr++)
+	  fprintf (stdout, "%02x ", Memory[addr]);
+
+	fputs (lineinfix + 3 * size, stdout);
+      }
+
+      fprintf (stdout, "\t.byt $%02x", Memory[address]);
+
+      for (counter = size, addr = address + 1; --counter; addr++)
+	if (addr < EndAddress) /* problems with this overflowing */
+		fprintf (stdout, ",$%02x", Memory[addr]);
+
+      fputc ('\n', stdout);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dxa.1	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,402 @@
+.TH DXA "1" "31 January 2007"
+
+.SH NAME
+dxa \- 6502/R65C02 disassembler
+
+.SH SYNOPSIS
+.B dxa
+[\fIOPTION\fR]... \fIFILE\fR
+
+.SH DESCRIPTION
+.B dxa
+is the semi-official disassembler option for the
+.BR xa (1)
+package, a weakly patched version of Marko Mäkelä's
+.B d65
+disassembler that generates output similar to the de facto coding
+conventions used for
+.BR xa (1).
+The package is designed to intelligently(?) scan arbitrary code and (with
+hints) can identify the difference between data and valid machine code,
+generating a sane looking, "perfect" disassembly with data and code portions.
+.LP
+Perfect, in this case, means that you can take what
+.B dxa
+spits out and feed it right back into
+.BR xa (1),
+and get the exact same object file you started with, even if sometimes
+.B dxa
+can't identify everything correctly. With a few extra options, you can tease
+and twist the output to generate something not quite so parseable, or even
+more like true assembler source.
+.SH OPTIONS
+For historical and compatibility reasons, the long options (--) only exist
+if
+.B dxa
+were compiled with LONG_OPTIONS enabled in options.h.
+.TP
+.B \--datablock xxxx-yyyy
+.TP
+.B \-b xxxx-yyyy
+Defines the memory range xxxx to yyyy (hexadecimal, inclusive) to be a data
+block. The memory range can be further specified:
+.RS
+.IP *
+If the range is preceded by ! (an exclamation point), such as
+.BR !c000-cfff ,
+then it is 
+further defined to be a data block with no vectors in it either.
+.IP *
+If the range is preceded by ? (a question mark), then it is further
+defined to be a data block that is completely unused and therefore
+no valid routine may contain instructions whose parameter lie in this
+range.  Useful for providing enhanced protection against misinterpreting
+data to be program code, but be careful, or some code may be listed as
+data.  For instance, the Commodore 64 firmware uses the base address $CFFF
+when initializing the video chip, and the BASIC interpreter uses the
+addresses $9FEA and $9FEB while loading the instruction pointers.
+In addition to this, there are a number of BIT instructions used for
+skipping the next instruction.  Thus, you must allow addresses like $1A9,
+$2A9 and so on.
+.RE
+.TP
+.B \--datablocks filename
+.TP
+.B \-B filename
+Reads data blocks from file
+.B filename
+as if they had been specified on the command
+line, one per line (such as xxxx-yyyy, ?xxxx-yyyy, etc.).
+.TP
+.B \--labels filename
+.TP
+.B \-l filename
+Causes label names to be read from file
+.BR filename .
+This file format is the same as the labelfile/symbol table file generated
+by
+.BR xa (1)
+with the
+.B \-l
+option. The
+.B \-l
+was chosen on purpose for consistency with
+.BR xa (1).
+.TP
+.B \--routine xxxx
+.TP
+.B \-r xxxx
+Specifies an address (in hexadecimal) that is declared to be a valid routine.
+.B It is strongly recommended
+that you specify the initial execution address as a routine.
+For example, for a Commodore 64 binary with a
+.B SYS 2064
+header, add
+.B \-r0810
+so that disassembly starts at that location. This may have interactions with
+datablock detection
+.RB ( \-d ).
+.TP
+.B \--routines filename
+.TP
+.B \-R filename
+Causes a list of routines to be read from file
+.BR filename ,
+one per line as if they had been specified on the command line.
+.TP
+.B \--addresses option
+.TP
+.B \-a option
+Determines if and what kind of address information should be dumped with the
+disassembly, if any. Note that this may make your output no longer intelligible
+to
+.BR xa (1).
+The valid options are:
+.RS
+.TP
+.B disabled
+Dump source only with no address information. This is the default.
+.TP
+.B enabled
+Write the current address at the beginning of each line.
+.TP
+.B dump
+Write the current address at the beginning of each line, along with a hexdump
+of the bytes for which the statement was generated.
+.RE
+.TP
+.B \--colon-newline
+.TP
+.B \-N
+.TP
+.B \--no-colon-newline
+.TP
+.B \-n
+A purely cosmetic option to determine how labels are emitted. Many people,
+including myself, prefer a listing where the label is given, then a tab,
+then the code
+.RB ( \-n ).
+Since this is
+.I my
+preference, it's the default. On the other hand, there are also many who
+prefer to have the label demarcated by a colon and a newline, and the code
+beginning indented on the next line. This is the way
+.B d65
+used to do it, and is still supported with
+.BR \-N .
+.TP
+.B \--processor option
+.TP
+.B \-p option
+Specify the instruction set. Note that specifying an instruction set that
+permits and disassembles illegal and/or undocumented
+NMOS opcodes may make your output unintelligible to
+.BR xa (1).
+Only one may be specified. The valid options are:
+.RS
+.TP
+.B standard-nmos6502
+Only official opcodes will be recognized. This is the default.
+.TP
+.B r65c02
+Opcodes specific to the Rockwell 65C02 (R65C02) will also be allowed.
+.TP
+.B all-nmos6502
+Allows all 256 NMOS opcodes to be disassembled, whether documented or
+undocumented.
+Note that instructions generated by this mode are not guaranteed to work on
+all NMOS 6502s.
+.TP
+.B rational-nmos6502
+Only allows "rational" undocumented instructions. This excludes ANE, SHA,
+SHS, SHY, SHX, LXA and LAXS. This is a judgment call.
+.TP
+.B useful-nmos6502
+Only allows "useful" undocumented instructions. This excludes ANE, SHA,
+SHS, SHY, SHX, LXA, LAXS, NOOP and STP. This is a judgment call.
+.TP
+.B traditional-nmos6502
+Only allows the most widely accepted undocumented instructions based on
+combinations of ALU and RMW operations. This excludes ANE, SHA, SHS, SHY,
+SHX, LXA, LAXS, NOOP, STP, ARR, ASR, ANC, SBX and USBC.
+This is a judgment call.
+.RE
+.TP
+.B \--get-sa
+.TP
+.B \-G
+.TP
+.B \--no-get-sa xxxx
+.TP
+.B \-g xxxx
+Enables or disables automatic starting address detection. If enabled (the
+default),
+.B dxa
+looks at the first two bytes as a 16-bit word in 6502 little-endian format
+and considers that to be the starting address for the object, discarding them
+without further interpretation. This is very useful for Commodore computers in
+particular. If your binary does not have a starting address, you must
+specify one using
+.B \-g
+or
+.B \--no-get-sa
+followed by a hexadecimal address. The starting address will then be encoded
+into the output using
+.BR "* =" .
+.TP
+.B \--no-word-sa
+.TP
+.B \-q
+.TP
+.B \--word-sa
+.TP
+.B \-Q
+Only relevant if automatic starting address detection is enabled. If so,
+the default is to also emit the starting address as a
+.B \&.word
+pseudo-op before the starting address indicated with
+.B * =
+so that it will be regenerated on re-assembly
+.RB ( \-Q ).
+Otherwise, if this option is disabled, the starting address word will not be
+re-emitted and
+will need to be tacked back on if the target requires it. If you specify an
+address with
+.BR \-g ,
+then that address will be used here too.
+.TP
+.B \--verbose
+.TP
+.B \-v
+Enables verbose output, which may or may not be useful in the same way that
+Schroedinger's Cat may or may not be dead.
+.TP
+.B \--help
+.TP
+.B \-?
+.TP
+.B \-V
+A quick summary of options.
+.LP
+The following options control how program code is scanned and determined
+to be a valid (or invalid) portion of a putative routine.
+.TP
+.B \--datablock-detection option
+.TP
+.B \-d option
+This controls how the program automatically detects data blocks for addresses
+where no previous hints are specified. Only one method may be specified.
+The valid options are:
+.RS
+.TP
+.B poor
+As much as the object as possible will be listed as program code, even if
+there are illegal instructions present. This is the default.
+.TP
+.B strict
+Assumes that all declared routines call and execute only valid instructions. If
+any portion of code declared as a routine leads to an address block containing
+illegal opcodes, a consistency error will occur and disassembly will stop.
+.TP
+.B skip-scanning
+Program addresses that are not referenced by any routine will not be scanned
+for valid routines (thus data a priori).
+.RE
+.TP
+.B \--no-external-labels
+.TP
+.B \-e
+.TP
+.B \--external-labels
+.TP
+.B \-E
+Controls whether labels should be generated for addresses outside of the
+program itself. The default is not to (i.e., leave the addresses absolute).
+.TP
+.B \--address-tables option
+.TP
+.B \-t option
+Controls detection of address tables/dispatch tables. The following options
+are available:
+.RS
+.TP
+.B ignore
+Don't attempt to detect address tables.
+.TP
+.B detect-all
+Address tables referencing any label will be detected.
+.TP
+.B detect-internal
+Address tables with labels whose addresses lie within the program's address
+range will be detected. This is the default.
+.RE
+.TP
+.B \--no-suspect-jsr
+.TP
+.B \-j
+.TP
+.B \--suspect-jsr
+.TP
+.B \-J
+These options indicate whether JSRs are always expected to return to the
+following instruction or not. This will affect how routines are parsed. For
+example, the Commodore 128 KERNAL has a routine called PRIMM that prints a
+null-terminated string directly following the JSR instruction, returning after
+the null byte. In this case,
+.B \-J
+should be specified to alert the disassembler that this is possible. The
+default is to expect "normal" JSRs (i.e.,
+.BR \-j ).
+.TP
+.B \--no-one-byte-routines
+.TP
+.B \-o
+.TP
+.B \--one-byte-routines
+.TP
+.B \-O
+These options permit or inhibit a single RTS, RTI or BRK instruction (or STP
+if enabled by the instruction set), or a conditional branch, from being
+automatically identified as a routine. The default is to inhibit this; specific
+cases may be selectively overridden with the
+.B \-r
+option.
+.TP
+.B \--no-stupid-jumps
+.TP
+.B \-m
+.TP
+.B \--stupid-jumps
+.TP
+.B \-M
+These options consider jumps or branches to the current address (such as
+JMP *, BCC *) to be invalid or valid code depending on which is specified.
+Note that BVC * is always accepted as the V flag can sometimes be toggled
+by an external hardware signal. The default is to consider them
+invalid otherwise.
+.TP
+.B \--no-allow-brk
+.TP
+.B \-w
+.TP
+.B \--allow-brk
+.TP
+.B \-W
+These options control if BRK (or STP if enabled by the instruction set) should
+be treated as a valid exit from a routine, just like RTS or RTI. The default
+is not to do so.
+.TP
+.B \--no-suspect-branches
+.TP
+.B \-c
+.TP
+.B \--suspect-branches
+.TP
+.B \-C
+These options are rarely needed, but account for the case where a program may
+intentionally obfuscate its code using branches with unusual destination
+addresses like LDA #2:BEQ *-1. In the default case, this would be considered
+to be invalid and not treated as a routine
+.RB ( \-c );
+if
+.B \-C
+is specified, it would be accepted as valid.
+.SH BUGS/TO-DO
+There are probably quite a few bugs yet to be found.
+.LP
+65816 opcodes are not (yet) supported.
+.LP
+The disassembler can easily be confused by the common idiom of tacking on
+BASIC text to call an appended ML routine. There probably should be a special
+case option for this. One workaround is to use the
+.B \--datablock
+option and specify the range as unused (such as in the case of
+.B 10 SYS2061
+(Commodore), giving
+.B \-b ?0801-080c
+to ignore that range as data).
+.LP
+There are a few options Marko created that aren't hooked up to anything (and
+are not documented here on purpose). I might finish these later.
+
+.SH "SEE ALSO"
+.BR xa (1),
+.BR file65 (1),
+.BR ldo65 (1),
+.BR printcbm (1),
+.BR reloc65 (1),
+.BR uncpk (1)
+
+.SH AUTHOR
+This manual page was written by Cameron Kaiser <ckaiser@floodgap.com>.
+.B dxa
+is based on
+.B d65
+0.2.1 by Marko Mäkelä.
+Original package (C)1993, 1994, 2000 Marko Mäkelä. Additional changes
+(C)2006 Cameron Kaiser.
+.B dxa
+is maintained independently.
+
+.SHWEBSITE
+http://www.floodgap.com/retrotech/xa/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/label.c	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,152 @@
+/*\
+ *  dxa v0.1.1 -- symbolic 65xx disassembler
+ *
+ *  Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+#define _LABEL_C_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "proto.h"
+#include "options.h"
+#include "opcodes.h"
+
+label *labeltable;
+char defaultlabel[5];
+unsigned numLabels = 0;
+
+#ifndef __STDC__
+void
+AddLabel (address, name)
+     ADDR_T address;
+     char *name;
+#else
+void AddLabel (ADDR_T address, char *name)
+#endif
+{
+  label *entry;
+  char *buffer;
+
+  if (!((buffer = malloc (strlen (name)))))
+    return;
+
+  entry = numLabels ?
+    realloc (labeltable, (numLabels + 1) * sizeof *entry) :
+    malloc (sizeof *entry);
+
+  if (!entry) return;
+
+  labeltable = entry;
+  entry = &labeltable[numLabels++];
+
+  entry->address = address;
+  entry->name = buffer;
+  while ((*buffer++ = *name++));
+}
+
+#ifndef __STDC__
+char *
+Label (address, admode)
+     ADDR_T address;
+     int admode;
+#else
+char *Label (ADDR_T address, int admode)
+#endif
+{
+  label *entry;
+
+  if (!IsLabeled (address)) {
+
+	/* dirty kludge to allow zero page stuff to still work. this sometimes
+		guesses wrong */
+	if (admode == zp)
+    		sprintf (defaultlabel, "$%02x", address);
+	else
+    		sprintf (defaultlabel, "$%04x", address);
+    return defaultlabel;
+  }
+
+  for (entry = &labeltable[numLabels]; entry-- > labeltable;)
+    if (entry->address == address)
+      return entry->name;
+
+  sprintf (defaultlabel, "l%x", address);
+
+  return defaultlabel;
+}
+
+#ifndef __STDC__
+void
+Collect ()
+#else
+void Collect (void)
+#endif
+{
+  unsigned counter = 0;
+  table *entry = NULL, *entry2;
+  label *labels;
+
+  if (fVerbose)
+    fprintf (stderr, "%s: collecting garbage.\n", prog);
+
+  while ((entry = entry2 = FindNextEntryType (entry, 0, 0))) {
+    counter++;
+
+    PutLabel (entry->address);
+    PutLowByte (entry->address);
+    PutHighByte (entry->address);
+
+    while ((entry2 = FindNextEntry (entry2, entry->address,
+                                    ~0, entry->type)))
+      DeleteEntry (entry2); /* remove duplicate warnings */
+  }
+
+  if ((entry = malloc (counter * sizeof *entry))) { /* compact the table */
+    entrycount = counter;
+
+    for (entry2 = scantable; counter; entry2++) {
+      if (!entry2->type) continue;
+
+      memcpy (&entry[--counter], entry2, sizeof *entry);
+    }
+
+    free (scantable);
+    scantable = entry;
+  }
+
+  for (labels = &labeltable[numLabels]; labels-- > labeltable;)
+    if ((ADDR_T)(labels->address - StartAddress) <
+        (ADDR_T)(EndAddress - StartAddress)) {
+      PutLabel (labels->address);
+      PutLowByte (labels->address);
+      PutHighByte (labels->address);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.c	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,540 @@
+/*\
+ *  dxa v0.1.3 -- symbolic 65xx disassembler
+ *
+ *  Based on d65 Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *  Changes for dxa (C) 2005, 2006 Cameron Kaiser
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Marko does not maintain dxa, so questions specific to dxa should be
+ *  sent to me at ckaiser@floodgap.com . Otherwise,
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+#define _MAIN_C_
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef __GNUC__
+#include <unistd.h>
+#endif
+#ifdef LONG_OPTIONS
+#include <getopt.h>
+#endif /* __GNUC__ */
+#include "proto.h"
+#include "options.h"
+#include "opcodes.h"
+
+#ifndef __STDC__
+int
+main (argc, argv)
+     int argc;
+     char **argv;
+#else
+int main (int argc, char **argv)
+#endif
+{
+  FILE *file;
+  unsigned address1, address2;
+#ifdef LONG_OPTIONS
+  int option_index;
+#endif
+  int fFinished = FALSE, fType;
+  char labelname[MAXLINE], strig[MAXLINE], *scanner;
+
+  extern char *optarg;
+  extern int optind;
+
+#ifdef LONG_OPTIONS
+  static struct option cmd_options [] = {
+    { "datablock", 1, 0, 'b' }, /* an address range to be marked
+                                   as a data block */
+    { "datablocks", 1, 0, 'B' },/* a file containing the address ranges
+                                   to be marked as data blocks */
+    { "labels", 1, 0, 'l' },    /* a file containing labels to be translated
+                                   in the output phase */
+    { "routine", 1, 0, 'r' },   /* an address of a routine */
+    { "routines", 1, 0, 'R' },  /* a file containing the addresses */
+
+    { "listing-width", 1, 0, 'L' },
+                                /* maximum number of dumped bytes per line */
+    { "addresses", 1, 0, 'a' }, /* dumping addresses in the output phase */
+    { "datablock-detection", 1, 0, 'd' },
+                                /* data block detection options */
+    { "processor", 1, 0, 'p' }, /* instruction set */
+    { "no-colon-newline", 0, 0, 'n' },
+    { "colon-newline", 0, 0, 'N' },
+    { "no-external-labels", 0, 0, 'e' },
+    { "external-labels", 0, 0, 'E' },
+    { "address-tables", 0, 0, 't' },
+    { "no-address-statements", 0, 0, 's' },
+    { "address-statements", 0, 0, 'S' },
+    { "suspect-jsr", 0, 0, 'J' },
+    { "no-suspect-jsr", 0, 0, 'j' },
+    { "one-byte-routines", 0, 0, 'O' },
+    { "no-one-byte-routines", 0, 0, 'o' },
+    { "stupid-jumps", 0, 0, 'M' },
+    { "no-stupid-jumps", 0, 0, 'm' },
+    { "allow-brk", 0, 0, 'W' },
+    { "no-allow-brk", 0, 0, 'w' },
+    { "suspect-branches", 0, 0, 'C' },
+    { "no-suspect-branches", 0, 0, 'c' },
+    { "cross-reference", 0, 0, 'X' },
+    { "no-cross-reference", 0, 0, 'x' },
+    { "verbose", 0, 0, 'v' },
+    { "help", 0, 0, '?' },
+    { "word-sa", 0, 0, 'Q' },
+    { "no-word-sa", 0, 0, 'q' },
+    { "get-sa", 0, 0, 'G' },
+    { "no-get-sa", 0, 0, 'g' },
+    { NULL, 0, 0, 0 }
+  };
+#endif /* LONG_OPTIONS */
+
+  opset = standard_nmos6502;
+
+  StartAddress = 0;
+  Options = O_ADR_ADR_DMP | B_LBL_ALWAYS | O_TBL_NOEXT |
+    B_STM_DETECT | B_STK_BALANCE | B_RSC_STRICT | O_DBL_STRICT |
+    B_JMP_STRICT | B_BRK_REJECT;
+
+	/* dxa defaults */
+        Options = (Options & ~M_ADDRESSES) | O_ADR_NOTHING;
+        Options = (Options & ~M_DATA_BLOCKS) | O_DBL_IGNORE;
+        Options &= ~B_LBL_ALWAYS;
+	Options &= ~B_LABCOL;
+	Options |= B_SA_WORD;
+	Options |= B_GET_SA;
+
+  for (address1 = sizeof MemType / sizeof *MemType; address1--;
+       MemType[address1] = 0);
+
+  for (address1 = sizeof MemFlag / sizeof *MemFlag; address1--;
+       MemFlag[address1] = MemLabel[address1] = 0);
+
+  for (address1 = sizeof LowByte / sizeof *LowByte; address1--;
+       HighByte[address1] = LowByte[address1] = 0);
+
+  for (prog = *argv; *prog; prog++);
+  for (;prog > *argv; prog--)
+    if (*prog == '/') {
+      prog++;
+      break;
+    }
+
+  while (!fFinished)
+#ifdef LONG_OPTIONS
+    switch (getopt_long (argc, argv,
+			 "?b:B:L:r:R:h:l:a:d:p:g:t:eEnNsSjJoOcCmMvVwWxXqQG",
+                         cmd_options, &option_index)) {
+#else
+    switch (getopt (argc, argv,
+	"?b:B:L:r:R:h:l:a:d:p:g:t:eEnNsSjJoOcCmMvVwWxXqQG")){
+#endif /* LONG_OPTIONS */
+    case -1:
+    case ':':
+      fFinished = TRUE;
+      break;
+
+    case '?':
+    case 'V':
+      goto Usage;
+
+    case 'b':
+      if (*optarg == '!') {
+        fType = MEM_PARAMETER;
+        optarg++;
+      }
+      else if (*optarg == '?') {
+        fType = MEM_UNPROCESSED;
+        optarg++;
+      }
+      else
+        fType = MEM_DATA;
+
+      if (!sscanf (optarg, "%X-%X", &address1, &address2) ||
+          address1 > 65535 || address2 > 65535) {
+        fprintf (stderr, "%s: Error in data block address range `%s'.\n\n",
+                 prog, optarg);
+        goto Usage;
+      }
+
+      for (; (ADDR_T)address1 != address2; address1++) {
+        SetMemType (address1, fType);
+        SetMemFlag (address1);
+      }
+
+      SetMemType (address1, fType);
+      SetMemFlag (address1);
+
+      break;
+
+    case 'B':
+      if (!((file = fopen (optarg, "rt")))) {
+        fprintf (stderr, "%s: Could not open %s.\n", prog, optarg);
+        return 2;
+      }
+
+      while (!feof (file)) {
+        if ('!' == (fType = fgetc (file)))
+          fType = MEM_PARAMETER;
+        else if ('?' == fType)
+          fType = MEM_UNPROCESSED;
+        else {
+          ungetc (fType, file);
+          fType = MEM_DATA;
+        }
+
+        if (!fscanf (file, "%X-%X\n", &address1, &address2) ||
+            address1 > 65535 || address2 > 65535) {
+          fprintf (stderr, "%s: Error in data block address file %s.\n",
+                   prog, optarg);
+
+          fclose (file);
+          return 3;
+        }
+
+        for (; (ADDR_T)address1 != address2; address1++) {
+          SetMemType (address1, fType);
+          SetMemFlag (address1);
+        }
+
+        SetMemType (address1, fType);
+        SetMemFlag (address1);
+      }
+
+      fclose (file);
+      break;
+
+    case 'r':
+      if (!sscanf (optarg, "%X", &address1) || address1 > 65535) {
+        fprintf (stderr, "%s: Error in routine address `%s'.\n\n",
+                 prog, optarg);
+        goto Usage;
+      }
+
+      AddEntry (address1, address1, RTN_SURE);
+      break;
+
+    case 'R':
+      if (!((file = fopen (optarg, "rt")))) {
+        fprintf (stderr, "%s: Could not open %s.\n", prog, optarg);
+        return 2;
+      }
+
+      while (!feof (file)) {
+        if (!fscanf (file, "%X\n", &address1) || address1 > 65535) {
+          fprintf (stderr, "%s: Error in data block address file `%s'.\n",
+                   prog, optarg);
+
+          fclose (file);
+          return 3;
+        }
+
+        AddEntry (address1, address1, RTN_SURE);
+      }
+
+      fclose (file);
+      break;
+
+    case 'L':
+      if (0 > (listwidth = atoi (optarg))) {
+	fprintf (stderr, "%s: Illegal listing width specified.\n\n", prog);
+	goto Usage;
+      }
+
+      break;
+
+    case 'a':
+      if (!strcmp (optarg, "disabled"))
+        Options = (Options & ~M_ADDRESSES) | O_ADR_NOTHING;
+      else if (!strcmp (optarg, "enabled"))
+        Options = (Options & ~M_ADDRESSES) | O_ADR_ADRPFIX;
+      else if (!strcmp (optarg, "dump"))
+        Options = (Options & ~M_ADDRESSES) | O_ADR_ADR_DMP;
+      else {
+        fprintf (stderr, "%s: Unrecognized option for dumping addresses.\n\n",
+                 prog);
+        goto Usage;
+      }
+      break;
+
+    case 'd':
+      if (!strcmp (optarg, "poor"))
+        Options = (Options & ~M_DATA_BLOCKS) | O_DBL_IGNORE;
+      else if (!strcmp (optarg, "extended"))
+        Options = (Options & ~M_DATA_BLOCKS) | O_DBL_DETECT;
+      else if (!strcmp (optarg, "skip-scanning"))
+        Options = (Options & ~M_DATA_BLOCKS) | O_DBL_NOSCAN;
+      else if (!strcmp (optarg, "strict"))
+        Options = (Options & ~M_DATA_BLOCKS) | O_DBL_STRICT;
+      else {
+        fprintf (stderr,
+                 "%s: Unrecognized option for detecting data blocks.\n\n",
+                 prog);
+        goto Usage;
+      }
+      break;
+
+    case 'p':
+      if (!strcmp (optarg, "all-nmos6502"))
+        opset = all_nmos6502;
+      else if (!strcmp (optarg, "rational-nmos6502"))
+        opset = rational_nmos6502;
+      else if (!strcmp (optarg, "useful-nmos6502"))
+        opset = useful_nmos6502;
+      else if (!strcmp (optarg, "traditional-nmos6502"))
+        opset = traditional_nmos6502;
+      else if (!strcmp (optarg, "r65c02"))
+        opset = r65c02;
+      else if (!strcmp (optarg, "standard-nmos6502"))
+        opset = standard_nmos6502;
+      else {
+        fprintf (stderr, "%s: Unsupported instruction set `%s'.\n\n",
+                 prog, optarg);
+        goto Usage;
+      }
+      break;
+
+    case 'e':
+      Options &= ~B_LBL_ALWAYS;
+      break;
+    case 'E':
+      Options |= B_LBL_ALWAYS;
+      break;
+
+    case 't':
+      if (!strcmp (optarg, "ignore"))
+        Options = (Options & ~M_ADR_TABLES) | O_TBL_IGNORE;
+      else if (!strcmp (optarg, "detect-all"))
+        Options = (Options & ~M_ADR_TABLES) | O_TBL_DETECT;
+      else if (!strcmp (optarg, "detect-internal"))
+        Options = (Options & ~M_ADR_TABLES) | O_TBL_NOEXT;
+      else {
+        fprintf (stderr,
+                 "%s: Unknown address table detection option `%s'.\n\n",
+                 prog, optarg);
+        goto Usage;
+      }
+      break;
+
+    case 's':
+      Options &= ~B_STM_DETECT;
+      break;
+    case 'S':
+      Options |= B_STM_DETECT;
+      break;
+
+    case 'J':
+      Options &= ~B_STK_BALANCE;
+      break;
+    case 'j':
+      Options |= B_STK_BALANCE;
+      break;
+
+    case 'o':
+      Options &= ~B_RSC_STRICT;
+      break;
+    case 'O':
+      Options |= B_RSC_STRICT;
+      break;
+
+    case 'c':
+      Options &= ~B_SCEPTIC;
+      break;
+    case 'C':
+      Options |= B_SCEPTIC;
+      break;
+
+    case 'M':
+      Options &= ~B_JMP_STRICT;
+      break;
+    case 'm':
+      Options |= B_JMP_STRICT;
+      break;
+
+    case 'v':
+      fVerbose = TRUE;
+      break;
+
+    case 'W':
+      Options &= ~B_BRK_REJECT;
+      break;
+    case 'w':
+      Options |= B_BRK_REJECT;
+      break;
+
+    case 'x':
+      Options &= ~B_CROSSREF;
+      break;
+    case 'X':
+      Options |= B_CROSSREF;
+      break;
+
+/* new or altered dxa options */
+    case 'n':
+	Options &= ~B_LABCOL;
+	break;
+    case 'N':
+	Options |= B_LABCOL;
+	break;
+    case 'q':
+	Options &= ~B_SA_WORD;
+	break;
+    case 'Q':
+	Options |= B_SA_WORD;
+	break;
+    case 'G':
+	Options |= B_GET_SA;
+	break;
+    case 'g':
+	Options &= ~B_GET_SA;
+        if (!sscanf (optarg, "%X", &address1) || address1 > 65535) {
+          fprintf (stderr, "%s: Error specifying starting address `%s'.\n\n",
+                 prog, optarg);
+          goto Usage;
+        }
+	StartAddress = address1;
+	break;
+    case 'l':
+      if (!((file = fopen (optarg, "rt")))) {
+        fprintf (stderr,
+                 "%s: Label file %s could not be opened for reading.\n\n",
+                 prog, optarg);
+
+        goto Usage;
+      }
+
+      while (!feof (file)) {
+        fType = fgetc (file);
+
+        if (feof (file))
+          break;
+
+        ungetc (fType, file);
+
+#if(0)
+	/* This is the old behaviour. -- Cameron */
+        if (!fscanf (file, "%X:", &address1) || address1 > 65535 || 
+            !fgets (labelname, sizeof labelname, file)) {
+#else
+	/* This is the xa-compatible label scanner. */
+	if (!fscanf(file, "%s%i", labelname, &address1) ||
+		address1 > 65535 ||
+		!fgets(strig, sizeof strig, file)) {
+#endif
+	LabelError:
+          fprintf (stderr, "%s: Error in label file %s.\n", prog, optarg);
+	  fprintf (stderr, "Address(?): 0x%x ... Label(?): \"%s\"\n\n",
+		address1, labelname);
+          fclose (file);
+          return 3;
+        }
+
+        for (scanner = labelname; *scanner; scanner++);
+
+#if(0)
+        if (scanner[-1] != '\n') goto LabelError; /* line too long */
+#endif
+
+        while (--scanner > labelname && (
+		*(unsigned char *)scanner < 32 ||
+		*(unsigned char *)scanner == 44)) /* and commas */
+          *scanner = 0;         /* remove trailing control characters */
+
+        for (scanner = labelname; *(unsigned char *)scanner < 32; scanner++)
+          if (!*scanner) goto LabelError;         /* label name missing */
+
+        AddLabel (address1, scanner);
+      }
+
+      fclose (file);
+    }
+
+  if (argc - optind > 1) {
+  Usage:
+    fprintf (stderr, "%s v0.1.3 -- symbolic 65xx disassembler\n", prog);
+    fprintf (stderr, "Based on d65 copyright (C) 1993-4 Marko M\"akel\"a\n");
+    fprintf (stderr, "Changes for dxa copyright (c) 2006-7 Cameron Kaiser\n\n");
+    fprintf (stderr, "Usage: %s [options] [filename]\n", prog);
+    return 1;
+  }
+
+	/* Fix, Need "rb" (binary mode) on Windows to avoid termintating on $1A */
+  if (!(file = (argc - optind) ? fopen (argv[argc - 1], "rb") : stdin)) {
+    fprintf (stderr, "%s: Couldn't open input file.\n", prog);
+    return 2;
+  }
+
+  if (Options & B_GET_SA) {
+  	StartAddress = (unsigned)fgetc (file);
+  	StartAddress |= (unsigned)fgetc (file) << 8;
+  }
+
+
+  if (feof (file)) {
+    fprintf (stderr, "%s: Error reading the file.\n", prog);
+    return 3;
+  }
+
+/* this doesn't work so well */
+/* AddEntry (StartAddress, StartAddress, RTN_SURE); */
+  EndAddress = StartAddress + fread (&Memory[StartAddress], sizeof (char),
+                                     65536 - StartAddress, file);
+
+  if (!feof (file)) {
+    if ((EndAddress = fread (Memory, sizeof (char), StartAddress, file)))
+      fprintf (stderr, "%s: Warning: Input file caused an address overflow.\n",
+               prog);
+
+    if (!feof (file)) {
+      fprintf (stderr, "%s: Error: Input file is longer than 64 kilobytes.\n",
+               prog);
+      fclose (file);
+      return 3;
+    }
+  }
+
+  fclose (file);
+
+  if (fVerbose)
+    fprintf (stderr, "%s: disassembling %X-%X\n", prog,
+             StartAddress, EndAddress);
+
+  if (ScanSpecified ()) {
+    fprintf (stderr, "\n%s: Invalid routine address(es) specified. Stop.\n",
+             prog);
+
+    return 4;
+  }
+
+  ScanPotentials ();
+  ScanTheRest ();
+  Collect ();
+  SearchVectors ();
+  Dump ();
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/opcodes.h	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,617 @@
+/*\
+ *  dxa v0.1.1 -- symbolic 65xx disassembler
+ *
+ *  Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *  Changes for dxa (C) 2006 Cameron Kaiser
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Marko does not maintain dxa, so questions specific to dxa should be
+ *  sent to me at ckaiser@floodgap.com . Otherwise,
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+/* opcodes.h - opcodes for different microprocessors */
+
+#ifndef _OPCODES_H_
+#define _OPCODES_H_
+
+#ifdef _DUMP_C_
+
+static char *mne[] = { "???", "lda", "ldx", "ldy", "sta", "stx", "sty",
+"stz", "adc", "sbc", "dec", "dex", "dey", "inc", "inx", "iny", "cmp",
+"cpx", "cpy", "bit", "and", "ora", "eor", "asl", "lsr", "rol", "ror",
+"tax", "tay", "tsx", "txs", "tya", "tad", "tas", "tda", "tsa", "txy",
+"tyx", "pha", "phx", "phy", "php", "pea", "pei", "per", "phb", "phd",
+"phk", "plb", "pld", "pla", "plx", "ply", "plp", "clc", "cld", "cli",
+"clv", "sec", "sed", "sei", "rep", "sep", "xba", "xce", "bcc", "bcs",
+"bne", "beq", "bra", "brl", "bpl", "bmi", "bvc", "bvs", "jmp", "jml",
+"jsr", "jsl", "rts", "rtl", "rti", "brk", "nop", "trb", "tsb", "wai",
+"bbr0", "bbr1", "bbr2", "bbr3", "bbr4", "bbr5", "bbr6", "bbr7",
+"bbs0", "bbs1", "bbs2", "bbs3", "bbs4", "bbs5", "bbs6", "bbs7",
+"rmb0", "rmb1", "rmb2", "rmb3", "rmb4", "rmb5", "rmb6", "rmb7",
+"smb0", "smb1", "smb2", "smb3", "smb4", "smb5", "smb6", "smb7", "cop",
+"mvn", "mvp", "laxs", "stax", "sha", "shx", "shy", "ane", "lxa", "lae",
+"shs", "sbx", "usbc", "dcmp", "isbc", "rlan", "rrad", "slor", "sreo",
+"arr", "asr", "anc", "noop", "stp", "txa", "ldax" };
+
+#endif /* _DUMP_C_ */
+
+enum
+{
+  S_ILLEGAL = 0, S_LDA, S_LDX, S_LDY, S_STA, S_STX, S_STY, S_STZ, S_ADC,
+  S_SBC, S_DEC, S_DEX, S_DEY, S_INC, S_INX, S_INY, S_CMP, S_CPX, S_CPY,
+  S_BIT, S_AND, S_ORA, S_EOR, S_ASL, S_LSR, S_ROL, S_ROR, S_TAX, S_TAY,
+  S_TSX, S_TXS, S_TYA, S_TAD, S_TAS, S_TDA, S_TSA, S_TXY, S_TYX, S_PHA,
+  S_PHX, S_PHY, S_PHP, S_PEA, S_PEI, S_PER, S_PHB, S_PHD, S_PHK, S_PLB,
+  S_PLD, S_PLA, S_PLX, S_PLY, S_PLP, S_CLC, S_CLD, S_CLI, S_CLV, S_SEC,
+  S_SED, S_SEI, S_REP, S_SEP, S_XBA, S_XCE, S_BCC, S_BCS, S_BNE, S_BEQ,
+  S_BRA, S_BRL, S_BPL, S_BMI, S_BVC, S_BVS, S_JMP, S_JML, S_JSR, S_JSL,
+  S_RTS, S_RTL, S_RTI, S_BRK, S_NOP, S_TRB, S_TSB, S_WAI,
+  S_BBR0, S_BBR1, S_BBR2, S_BBR3, S_BBR4, S_BBR5, S_BBR6, S_BBR7,
+  S_BBS0, S_BBS1, S_BBS2, S_BBS3, S_BBS4, S_BBS5, S_BBS6, S_BBS7,
+  S_RMB0, S_RMB1, S_RMB2, S_RMB3, S_RMB4, S_RMB5, S_RMB6, S_RMB7,
+  S_SMB0, S_SMB1, S_SMB2, S_SMB3, S_SMB4, S_SMB5, S_SMB6, S_SMB7,
+  S_COP, S_MVN, S_MVP, S_LAXS, S_STAX, S_SHA, S_SHX, S_SHY, S_ANE, S_LXA,
+  S_LAE, S_SHS, S_SBX, S_USBC, S_DCMP, S_ISBC, S_RLAN, S_RRAD, S_SLOR,
+  S_SREO, S_ARR, S_ASR, S_ANC, S_NOOP, S_STP, S_TXA, S_LDAX
+};
+
+enum
+{
+  accu=0, imm, abso, zp, zpx, zpy, absx, absy,
+  iabsx, impl, rel, zrel, indx, indy, iabs, ind
+};
+
+#ifdef _DUMP_C_
+static char *prefix[] = { "", "#", "", "", "", "", "", "",
+                          "(", "", "", "", "(", "(", "(", "(" };
+
+/* static char *postfix[] = { " A", "", "", "", ",X", ",Y", ",X", ",Y", */
+static char *postfix[] = { "", "", "", "", ",x", ",y", ",x", ",y", 
+                           ",x)", "", "", "", ",x)", "),y", ")", ")" };
+#endif /* _DUMP_C_ */
+
+/* Adressing mode types. */
+enum
+{
+  absindir, /* absolute parameter (8 or 16 bits) for indirection */
+  absolute, /* absolute parameter (8 or 16 bits), not indexed */
+  other,    /* something else (except impimm) */
+  impimm    /* implied or immediate parameter */
+};
+
+#ifndef _SCAN_C_
+extern unsigned int types[];
+#else
+unsigned int types[] = { impimm, impimm, absolute, absolute, other, other,
+                         other, other, other, impimm, other, other,
+                         other, absindir, absindir, absindir };
+#endif
+
+/* Number of bytes that instructions of different addressing modes occupy */
+#ifndef _SCAN_C_
+extern unsigned int sizes[];
+#else
+unsigned int sizes[] = { 1, 2, 3, 2, 2, 2, 3, 3, 3, 1, 2, 3, 2, 2, 3, 2 };
+#endif
+
+typedef struct opcodes
+{
+  int mnemonic; /* index to mnemonic instruction name table */
+  int admode;   /* addressing mode */
+} opcodes;
+
+#ifndef _MAIN_C_
+extern
+#endif
+opcodes *opset;
+
+#ifdef _MAIN_C_
+opcodes all_nmos6502[] =
+{
+  {S_BRK, impl}, {S_ORA, indx}, {S_STP, impl}, {S_SLOR,indx},
+  {S_NOOP,  zp}, {S_ORA,   zp}, {S_ASL,   zp}, {S_SLOR,  zp},
+  {S_PHP, impl}, {S_ORA,  imm}, {S_ASL, accu}, {S_ANC,  imm},
+  {S_NOOP,abso}, {S_ORA, abso}, {S_ASL, abso}, {S_SLOR, abso},
+  {S_BPL,  rel}, {S_ORA, indy}, {S_STP, impl}, {S_SLOR,indy},
+  {S_NOOP, zpx}, {S_ORA,  zpx}, {S_ASL,  zpx}, {S_SLOR, zpx},
+  {S_CLC, impl}, {S_ORA, absy}, {S_NOOP,impl}, {S_SLOR,absy},
+  {S_NOOP,absx}, {S_ORA, absx}, {S_ASL, absx}, {S_SLOR,absx},
+
+  {S_JSR, abso}, {S_AND, indx}, {S_STP, impl}, {S_RLAN,indx},
+  {S_BIT,   zp}, {S_AND,   zp}, {S_ROL,   zp}, {S_RLAN,  zp},
+  {S_PLP, impl}, {S_AND,  imm}, {S_ROL, accu}, {S_ANC,  imm},
+  {S_BIT, abso}, {S_AND, abso}, {S_ROL, abso}, {S_RLAN,abso},
+  {S_BMI,  rel}, {S_AND, indy}, {S_STP, impl}, {S_RLAN,indy},
+  {S_NOOP, zpx}, {S_AND,  zpx}, {S_ROL,  zpx}, {S_RLAN, zpx},
+  {S_SEC, impl}, {S_AND, absy}, {S_NOOP,impl}, {S_RLAN,absy},
+  {S_NOOP,absx}, {S_AND, absx}, {S_ROL, absx}, {S_RLAN,absx},
+
+  {S_RTI, impl}, {S_EOR, indx}, {S_STP, impl}, {S_SREO,indx},
+  {S_NOOP,  zp}, {S_EOR,   zp}, {S_LSR,   zp}, {S_SREO,  zp},
+  {S_PHA, impl}, {S_EOR,  imm}, {S_LSR, accu}, {S_ASR,  imm},
+  {S_JMP, abso}, {S_EOR, abso}, {S_LSR, abso}, {S_SREO,abso},
+  {S_BVC,  rel}, {S_EOR, indy}, {S_STP, impl}, {S_SREO,indy},
+  {S_NOOP, zpx}, {S_EOR,  zpx}, {S_LSR,  zpx}, {S_SREO, zpx},
+  {S_CLI, impl}, {S_EOR, absy}, {S_NOOP,impl}, {S_SREO,absy},
+  {S_NOOP,absx}, {S_EOR, absx}, {S_LSR, absx}, {S_SREO,absx},
+
+  {S_RTS, impl}, {S_ADC, indx}, {S_STP, impl}, {S_RRAD,indx},
+  {S_NOOP,  zp}, {S_ADC,   zp}, {S_ROR,   zp}, {S_RRAD,  zp},
+  {S_PLA, impl}, {S_ADC,  imm}, {S_ROR, accu}, {S_ARR,  imm},
+  {S_JMP, iabs}, {S_ADC, abso}, {S_ROR, abso}, {S_RRAD,abso},
+  {S_BVS,  rel}, {S_ADC, indy}, {S_STP, impl}, {S_RRAD,indy},
+  {S_NOOP, zpx}, {S_ADC,  zpx}, {S_ROR,  zpx}, {S_RRAD, zpx},
+  {S_SEI, impl}, {S_ADC, absy}, {S_NOOP,impl}, {S_RRAD,absy},
+  {S_NOOP,absx}, {S_ADC, absx}, {S_ROR, absx}, {S_RRAD,absx},
+
+  {S_NOOP, imm}, {S_STA, indx}, {S_NOOP, imm}, {S_STAX,indx},
+  {S_STY,   zp}, {S_STA,   zp}, {S_STX,   zp}, {S_STAX,  zp},
+  {S_DEY, impl}, {S_NOOP, imm}, {S_TXA, impl}, {S_ANE,  imm},
+  {S_STY, abso}, {S_STA, abso}, {S_STX, abso}, {S_STAX,abso},
+  {S_BCC,  rel}, {S_STA, indy}, {S_STP, impl}, {S_SHA, indy},
+  {S_STY,  zpx}, {S_STA,  zpx}, {S_STX,  zpy}, {S_STAX, zpy},
+  {S_TYA, impl}, {S_STA, absy}, {S_TXS, impl}, {S_SHS, absy},
+  {S_SHY, absx}, {S_STA, absx}, {S_SHX, absx}, {S_SHA, absx},
+
+  {S_LDY,  imm}, {S_LDA, indx}, {S_LDX,  imm}, {S_LDAX,indy},
+  {S_LDY,   zp}, {S_LDA,   zp}, {S_LDX,   zp}, {S_LDAX,  zp},
+  {S_TAY, impl}, {S_LDA,  imm}, {S_TAX, impl}, {S_LXA,  imm},
+  {S_LDY, abso}, {S_LDA, abso}, {S_LDX, abso}, {S_LDAX,abso},
+  {S_BCS,  rel}, {S_LDA, indy}, {S_STP, impl}, {S_LDAX,indy},
+  {S_LDY,  zpx}, {S_LDA,  zpx}, {S_LDX,  zpy}, {S_LDAX, zpy},
+  {S_CLV, impl}, {S_LDA, absy}, {S_TSX, impl}, {S_LAXS,absy},
+  {S_LDY, absx}, {S_LDA, absx}, {S_LDX, absy}, {S_LDAX,absy},
+
+  {S_CPY,  imm}, {S_CMP, indx}, {S_NOOP, imm}, {S_DCMP,indx},
+  {S_CPY,   zp}, {S_CMP,   zp}, {S_DEC,   zp}, {S_DCMP,  zp},
+  {S_INY, impl}, {S_CMP,  imm}, {S_DEX, impl}, {S_SBX,  imm},
+  {S_CPY, abso}, {S_CMP, abso}, {S_DEC, abso}, {S_DCMP,abso},
+  {S_BNE,  rel}, {S_CMP, indy}, {S_STP, impl}, {S_DCMP,indy},
+  {S_NOOP, zpx}, {S_CMP,  zpx}, {S_DEC,  zpx}, {S_DCMP, zpx},
+  {S_CLD, impl}, {S_CMP, absy}, {S_NOOP,impl}, {S_DCMP,absy},
+  {S_NOOP,absx}, {S_CMP, absx}, {S_DEC, absx}, {S_DCMP,absx},
+
+  {S_CPX,  imm}, {S_SBC, indx}, {S_NOOP, imm}, {S_ISBC,indx},
+  {S_CPX,   zp}, {S_SBC,   zp}, {S_INC,   zp}, {S_ISBC,  zp},
+  {S_INX, impl}, {S_SBC,  imm}, {S_NOP, impl}, {S_USBC, imm},
+  {S_CPX, abso}, {S_SBC, abso}, {S_INC, abso}, {S_ISBC,abso},
+  {S_BEQ,  rel}, {S_SBC, indy}, {S_STP, impl}, {S_ISBC,indy},
+  {S_NOOP, zpx}, {S_SBC,  zpx}, {S_INC,  zpx}, {S_ISBC, zpx},
+  {S_SED, impl}, {S_SBC, absy}, {S_NOOP,impl}, {S_ISBC,absy},
+  {S_NOOP,absx}, {S_SBC, absx}, {S_INC, absx}, {S_ISBC,absx},
+};
+
+/*\
+ * The following NMOS 6502 instructions are missing from the
+ * rational_nmos6502 map:
+ *
+ *   ANE  SHA  SHS  SHY  SHX  LXA  LAXS
+\*/
+
+opcodes rational_nmos6502[] =
+{
+  {S_BRK, impl}, {S_ORA, indx}, {S_STP, impl}, {S_SLOR,indx},
+  {S_NOOP,  zp}, {S_ORA,   zp}, {S_ASL,   zp}, {S_SLOR,  zp},
+  {S_PHP, impl}, {S_ORA,  imm}, {S_ASL, accu}, {S_ANC,  imm},
+  {S_NOOP,abso}, {S_ORA, abso}, {S_ASL, abso}, {S_SLOR, abso},
+  {S_BPL,  rel}, {S_ORA, indy}, {S_STP, impl}, {S_SLOR,indy},
+  {S_NOOP, zpx}, {S_ORA,  zpx}, {S_ASL,  zpx}, {S_SLOR, zpx},
+  {S_CLC, impl}, {S_ORA, absy}, {S_NOOP,impl}, {S_SLOR,absy},
+  {S_NOOP,absx}, {S_ORA, absx}, {S_ASL, absx}, {S_SLOR,absx},
+
+  {S_JSR, abso}, {S_AND, indx}, {S_STP, impl}, {S_RLAN,indx},
+  {S_BIT,   zp}, {S_AND,   zp}, {S_ROL,   zp}, {S_RLAN,  zp},
+  {S_PLP, impl}, {S_AND,  imm}, {S_ROL, accu}, {S_ANC,  imm},
+  {S_BIT, abso}, {S_AND, abso}, {S_ROL, abso}, {S_RLAN,abso},
+  {S_BMI,  rel}, {S_AND, indy}, {S_STP, impl}, {S_RLAN,indy},
+  {S_NOOP, zpx}, {S_AND,  zpx}, {S_ROL,  zpx}, {S_RLAN, zpx},
+  {S_SEC, impl}, {S_AND, absy}, {S_NOOP,impl}, {S_RLAN,absy},
+  {S_NOOP,absx}, {S_AND, absx}, {S_ROL, absx}, {S_RLAN,absx},
+
+  {S_RTI, impl}, {S_EOR, indx}, {S_STP, impl}, {S_SREO,indx},
+  {S_NOOP,  zp}, {S_EOR,   zp}, {S_LSR,   zp}, {S_SREO,  zp},
+  {S_PHA, impl}, {S_EOR,  imm}, {S_LSR, accu}, {S_ASR,  imm},
+  {S_JMP, abso}, {S_EOR, abso}, {S_LSR, abso}, {S_SREO,abso},
+  {S_BVC,  rel}, {S_EOR, indy}, {S_STP, impl}, {S_SREO,indy},
+  {S_NOOP, zpx}, {S_EOR,  zpx}, {S_LSR,  zpx}, {S_SREO, zpx},
+  {S_CLI, impl}, {S_EOR, absy}, {S_NOOP,impl}, {S_SREO,absy},
+  {S_NOOP,absx}, {S_EOR, absx}, {S_LSR, absx}, {S_SREO,absx},
+
+  {S_RTS, impl}, {S_ADC, indx}, {S_STP, impl}, {S_RRAD,indx},
+  {S_NOOP,  zp}, {S_ADC,   zp}, {S_ROR,   zp}, {S_RRAD,  zp},
+  {S_PLA, impl}, {S_ADC,  imm}, {S_ROR, accu}, {S_ARR,  imm},
+  {S_JMP, iabs}, {S_ADC, abso}, {S_ROR, abso}, {S_RRAD,abso},
+  {S_BVS,  rel}, {S_ADC, indy}, {S_STP, impl}, {S_RRAD,indy},
+  {S_NOOP, zpx}, {S_ADC,  zpx}, {S_ROR,  zpx}, {S_RRAD, zpx},
+  {S_SEI, impl}, {S_ADC, absy}, {S_NOOP,impl}, {S_RRAD,absy},
+  {S_NOOP,absx}, {S_ADC, absx}, {S_ROR, absx}, {S_RRAD,absx},
+
+  {S_NOOP, imm}, {S_STA, indx}, {S_NOOP, imm}, {S_STAX,indx},
+  {S_STY,   zp}, {S_STA,   zp}, {S_STX,   zp}, {S_STAX,  zp},
+  {S_DEY, impl}, {S_NOOP, imm}, {S_TXA, impl}, {S_ILLEGAL,0},
+  {S_STY, abso}, {S_STA, abso}, {S_STX, abso}, {S_STAX,abso},
+  {S_BCC,  rel}, {S_STA, indy}, {S_STP, impl}, {S_ILLEGAL,0},
+  {S_STY,  zpx}, {S_STA,  zpx}, {S_STX,  zpy}, {S_STAX, zpy},
+  {S_TYA, impl}, {S_STA, absy}, {S_TXS, impl}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_STA, absx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+
+  {S_LDY,  imm}, {S_LDA, indx}, {S_LDX,  imm}, {S_LDAX,indy},
+  {S_LDY,   zp}, {S_LDA,   zp}, {S_LDX,   zp}, {S_LDAX,  zp},
+  {S_TAY, impl}, {S_LDA,  imm}, {S_TAX, impl}, {S_ILLEGAL,0},
+  {S_LDY, abso}, {S_LDA, abso}, {S_LDX, abso}, {S_LDAX,abso},
+  {S_BCS,  rel}, {S_LDA, indy}, {S_STP, impl}, {S_LDAX,indy},
+  {S_LDY,  zpx}, {S_LDA,  zpx}, {S_LDX,  zpy}, {S_LDAX, zpy},
+  {S_CLV, impl}, {S_LDA, absy}, {S_TSX, impl}, {S_ILLEGAL,0},
+  {S_LDY, absx}, {S_LDA, absx}, {S_LDX, absy}, {S_LDAX,absy},
+
+  {S_CPY,  imm}, {S_CMP, indx}, {S_NOOP, imm}, {S_DCMP,indx},
+  {S_CPY,   zp}, {S_CMP,   zp}, {S_DEC,   zp}, {S_DCMP,  zp},
+  {S_INY, impl}, {S_CMP,  imm}, {S_DEX, impl}, {S_SBX,  imm},
+  {S_CPY, abso}, {S_CMP, abso}, {S_DEC, abso}, {S_DCMP,abso},
+  {S_BNE,  rel}, {S_CMP, indy}, {S_STP, impl}, {S_DCMP,indy},
+  {S_NOOP, zpx}, {S_CMP,  zpx}, {S_DEC,  zpx}, {S_DCMP, zpx},
+  {S_CLD, impl}, {S_CMP, absy}, {S_NOOP,impl}, {S_DCMP,absy},
+  {S_NOOP,absx}, {S_CMP, absx}, {S_DEC, absx}, {S_DCMP,absx},
+
+  {S_CPX,  imm}, {S_SBC, indx}, {S_NOOP, imm}, {S_ISBC,indx},
+  {S_CPX,   zp}, {S_SBC,   zp}, {S_INC,   zp}, {S_ISBC,  zp},
+  {S_INX, impl}, {S_SBC,  imm}, {S_NOP, impl}, {S_USBC, imm},
+  {S_CPX, abso}, {S_SBC, abso}, {S_INC, abso}, {S_ISBC,abso},
+  {S_BEQ,  rel}, {S_SBC, indy}, {S_STP, impl}, {S_ISBC,indy},
+  {S_NOOP, zpx}, {S_SBC,  zpx}, {S_INC,  zpx}, {S_ISBC, zpx},
+  {S_SED, impl}, {S_SBC, absy}, {S_NOOP,impl}, {S_ISBC,absy},
+  {S_NOOP,absx}, {S_SBC, absx}, {S_INC, absx}, {S_ISBC,absx},
+};
+
+/*\
+ * The following NMOS 6502 instructions are missing from the
+ * useful_nmos6502 map:
+ *
+ *   ANE  SHA  SHS  SHY  SHX  LXA  LAXS  NOOP  STP
+\*/
+
+opcodes useful_nmos6502[] =
+{
+  {S_BRK, impl}, {S_ORA, indx}, {S_ILLEGAL,0}, {S_SLOR,indx},
+  {S_ILLEGAL,0}, {S_ORA,   zp}, {S_ASL,   zp}, {S_SLOR,  zp},
+  {S_PHP, impl}, {S_ORA,  imm}, {S_ASL, accu}, {S_ANC,  imm},
+  {S_ILLEGAL,0}, {S_ORA, abso}, {S_ASL, abso}, {S_SLOR,abso},
+  {S_BPL,  rel}, {S_ORA, indy}, {S_ILLEGAL,0}, {S_SLOR,indy},
+  {S_ILLEGAL,0}, {S_ORA,  zpx}, {S_ASL,  zpx}, {S_SLOR, zpx},
+  {S_CLC, impl}, {S_ORA, absy}, {S_ILLEGAL,0}, {S_SLOR,absy},
+  {S_ILLEGAL,0}, {S_ORA, absx}, {S_ASL, absx}, {S_SLOR,absx},
+
+  {S_JSR, abso}, {S_AND, indx}, {S_ILLEGAL,0}, {S_RLAN,indx},
+  {S_BIT,   zp}, {S_AND,   zp}, {S_ROL,   zp}, {S_RLAN,  zp},
+  {S_PLP, impl}, {S_AND,  imm}, {S_ROL, accu}, {S_ANC,  imm},
+  {S_BIT, abso}, {S_AND, abso}, {S_ROL, abso}, {S_RLAN,abso},
+  {S_BMI,  rel}, {S_AND, indy}, {S_ILLEGAL,0}, {S_RLAN,indy},
+  {S_ILLEGAL,0}, {S_AND,  zpx}, {S_ROL,  zpx}, {S_RLAN, zpx},
+  {S_SEC, impl}, {S_AND, absy}, {S_ILLEGAL,0}, {S_RLAN,absy},
+  {S_ILLEGAL,0}, {S_AND, absx}, {S_ROL, absx}, {S_RLAN,absx},
+
+  {S_RTI, impl}, {S_EOR, indx}, {S_ILLEGAL,0}, {S_SREO,indx},
+  {S_ILLEGAL,0}, {S_EOR,   zp}, {S_LSR,   zp}, {S_SREO,  zp},
+  {S_PHA, impl}, {S_EOR,  imm}, {S_LSR, accu}, {S_ASR,  imm},
+  {S_JMP, abso}, {S_EOR, abso}, {S_LSR, abso}, {S_SREO,abso},
+  {S_BVC,  rel}, {S_EOR, indy}, {S_ILLEGAL,0}, {S_SREO,indy},
+  {S_ILLEGAL,0}, {S_EOR,  zpx}, {S_LSR,  zpx}, {S_SREO, zpx},
+  {S_CLI, impl}, {S_EOR, absy}, {S_ILLEGAL,0}, {S_SREO,absy},
+  {S_ILLEGAL,0}, {S_EOR, absx}, {S_LSR, absx}, {S_SREO,absx},
+
+  {S_RTS, impl}, {S_ADC, indx}, {S_ILLEGAL,0}, {S_RRAD,indx},
+  {S_ILLEGAL,0}, {S_ADC,   zp}, {S_ROR,   zp}, {S_RRAD,  zp},
+  {S_PLA, impl}, {S_ADC,  imm}, {S_ROR, accu}, {S_ARR,  imm},
+  {S_JMP, iabs}, {S_ADC, abso}, {S_ROR, abso}, {S_RRAD,abso},
+  {S_BVS,  rel}, {S_ADC, indy}, {S_ILLEGAL,0}, {S_RRAD,indy},
+  {S_ILLEGAL,0}, {S_ADC,  zpx}, {S_ROR,  zpx}, {S_RRAD, zpx},
+  {S_SEI, impl}, {S_ADC, absy}, {S_ILLEGAL,0}, {S_RRAD,absy},
+  {S_ILLEGAL,0}, {S_ADC, absx}, {S_ROR, absx}, {S_RRAD,absx},
+
+  {S_ILLEGAL,0}, {S_STA, indx}, {S_ILLEGAL,0}, {S_STAX,indx},
+  {S_STY,   zp}, {S_STA,   zp}, {S_STX,   zp}, {S_STAX,  zp},
+  {S_DEY, impl}, {S_ILLEGAL,0}, {S_TXA, impl}, {S_ILLEGAL,0},
+  {S_STY, abso}, {S_STA, abso}, {S_STX, abso}, {S_STAX,abso},
+  {S_BCC,  rel}, {S_STA, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_STY,  zpx}, {S_STA,  zpx}, {S_STX,  zpy}, {S_STAX, zpy},
+  {S_TYA, impl}, {S_STA, absy}, {S_TXS, impl}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_STA, absx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+
+  {S_LDY,  imm}, {S_LDA, indx}, {S_LDX,  imm}, {S_LDAX,indy},
+  {S_LDY,   zp}, {S_LDA,   zp}, {S_LDX,   zp}, {S_LDAX,  zp},
+  {S_TAY, impl}, {S_LDA,  imm}, {S_TAX, impl}, {S_ILLEGAL,0},
+  {S_LDY, abso}, {S_LDA, abso}, {S_LDX, abso}, {S_LDAX,abso},
+  {S_BCS,  rel}, {S_LDA, indy}, {S_ILLEGAL,0}, {S_LDAX,indy},
+  {S_LDY,  zpx}, {S_LDA,  zpx}, {S_LDX,  zpy}, {S_LDAX, zpy},
+  {S_CLV, impl}, {S_LDA, absy}, {S_TSX, impl}, {S_ILLEGAL,0},
+  {S_LDY, absx}, {S_LDA, absx}, {S_LDX, absy}, {S_LDAX,absy},
+
+  {S_CPY,  imm}, {S_CMP, indx}, {S_ILLEGAL,0}, {S_DCMP,indx},
+  {S_CPY,   zp}, {S_CMP,   zp}, {S_DEC,   zp}, {S_DCMP,  zp},
+  {S_INY, impl}, {S_CMP,  imm}, {S_DEX, impl}, {S_SBX,  imm},
+  {S_CPY, abso}, {S_CMP, abso}, {S_DEC, abso}, {S_DCMP,abso},
+  {S_BNE,  rel}, {S_CMP, indy}, {S_ILLEGAL,0}, {S_DCMP,indy},
+  {S_ILLEGAL,0}, {S_CMP,  zpx}, {S_DEC,  zpx}, {S_DCMP, zpx},
+  {S_CLD, impl}, {S_CMP, absy}, {S_ILLEGAL,0}, {S_DCMP,absy},
+  {S_ILLEGAL,0}, {S_CMP, absx}, {S_DEC, absx}, {S_DCMP,absx},
+
+  {S_CPX,  imm}, {S_SBC, indx}, {S_ILLEGAL,0}, {S_ISBC,indx},
+  {S_CPX,   zp}, {S_SBC,   zp}, {S_INC,   zp}, {S_ISBC,  zp},
+  {S_INX, impl}, {S_SBC,  imm}, {S_NOP, impl}, {S_USBC, imm},
+  {S_CPX, abso}, {S_SBC, abso}, {S_INC, abso}, {S_ISBC,abso},
+  {S_BEQ,  rel}, {S_SBC, indy}, {S_ILLEGAL,0}, {S_ISBC,indy},
+  {S_ILLEGAL,0}, {S_SBC,  zpx}, {S_INC,  zpx}, {S_ISBC, zpx},
+  {S_SED, impl}, {S_SBC, absy}, {S_ILLEGAL,0}, {S_ISBC,absy},
+  {S_ILLEGAL,0}, {S_SBC, absx}, {S_INC, absx}, {S_ISBC,absx},
+};
+
+/*\
+ * The following NMOS 6502 instructions are missing from the
+ * traditional_nmos6502 map:
+ *
+ *   ANE  SHA  SHS  SHY  SHX  LXA  LAXS  NOOP  STP
+ *   ARR  ASR  ANC  SBX  USBC
+\*/
+
+opcodes traditional_nmos6502[] =
+{
+  {S_BRK, impl}, {S_ORA, indx}, {S_ILLEGAL,0}, {S_SLOR,indx},
+  {S_ILLEGAL,0}, {S_ORA,   zp}, {S_ASL,   zp}, {S_SLOR,  zp},
+  {S_PHP, impl}, {S_ORA,  imm}, {S_ASL, accu}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_ORA, abso}, {S_ASL, abso}, {S_SLOR,abso},
+  {S_BPL,  rel}, {S_ORA, indy}, {S_ILLEGAL,0}, {S_SLOR,indy},
+  {S_ILLEGAL,0}, {S_ORA,  zpx}, {S_ASL,  zpx}, {S_SLOR, zpx},
+  {S_CLC, impl}, {S_ORA, absy}, {S_ILLEGAL,0}, {S_SLOR,absy},
+  {S_ILLEGAL,0}, {S_ORA, absx}, {S_ASL, absx}, {S_SLOR,absx},
+
+  {S_JSR, abso}, {S_AND, indx}, {S_ILLEGAL,0}, {S_RLAN,indx},
+  {S_BIT,   zp}, {S_AND,   zp}, {S_ROL,   zp}, {S_RLAN,  zp},
+  {S_PLP, impl}, {S_AND,  imm}, {S_ROL, accu}, {S_ILLEGAL,0},
+  {S_BIT, abso}, {S_AND, abso}, {S_ROL, abso}, {S_RLAN,abso},
+  {S_BMI,  rel}, {S_AND, indy}, {S_ILLEGAL,0}, {S_RLAN,indy},
+  {S_ILLEGAL,0}, {S_AND,  zpx}, {S_ROL,  zpx}, {S_RLAN, zpx},
+  {S_SEC, impl}, {S_AND, absy}, {S_ILLEGAL,0}, {S_RLAN,absy},
+  {S_ILLEGAL,0}, {S_AND, absx}, {S_ROL, absx}, {S_RLAN,absx},
+
+  {S_RTI, impl}, {S_EOR, indx}, {S_ILLEGAL,0}, {S_SREO,indx},
+  {S_ILLEGAL,0}, {S_EOR,   zp}, {S_LSR,   zp}, {S_SREO,  zp},
+  {S_PHA, impl}, {S_EOR,  imm}, {S_LSR, accu}, {S_ILLEGAL,0},
+  {S_JMP, abso}, {S_EOR, abso}, {S_LSR, abso}, {S_SREO,abso},
+  {S_BVC,  rel}, {S_EOR, indy}, {S_ILLEGAL,0}, {S_SREO,indy},
+  {S_ILLEGAL,0}, {S_EOR,  zpx}, {S_LSR,  zpx}, {S_SREO, zpx},
+  {S_CLI, impl}, {S_EOR, absy}, {S_ILLEGAL,0}, {S_SREO,absy},
+  {S_ILLEGAL,0}, {S_EOR, absx}, {S_LSR, absx}, {S_SREO,absx},
+
+  {S_RTS, impl}, {S_ADC, indx}, {S_ILLEGAL,0}, {S_RRAD,indx},
+  {S_ILLEGAL,0}, {S_ADC,   zp}, {S_ROR,   zp}, {S_RRAD,  zp},
+  {S_PLA, impl}, {S_ADC,  imm}, {S_ROR, accu}, {S_ILLEGAL,0},
+  {S_JMP, iabs}, {S_ADC, abso}, {S_ROR, abso}, {S_RRAD,abso},
+  {S_BVS,  rel}, {S_ADC, indy}, {S_ILLEGAL,0}, {S_RRAD,indy},
+  {S_ILLEGAL,0}, {S_ADC,  zpx}, {S_ROR,  zpx}, {S_RRAD, zpx},
+  {S_SEI, impl}, {S_ADC, absy}, {S_ILLEGAL,0}, {S_RRAD,absy},
+  {S_ILLEGAL,0}, {S_ADC, absx}, {S_ROR, absx}, {S_RRAD,absx},
+
+  {S_ILLEGAL,0}, {S_STA, indx}, {S_ILLEGAL,0}, {S_STAX,indx},
+  {S_STY,   zp}, {S_STA,   zp}, {S_STX,   zp}, {S_STAX,  zp},
+  {S_DEY, impl}, {S_ILLEGAL,0}, {S_TXA, impl}, {S_ILLEGAL,0},
+  {S_STY, abso}, {S_STA, abso}, {S_STX, abso}, {S_STAX,abso},
+  {S_BCC,  rel}, {S_STA, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_STY,  zpx}, {S_STA,  zpx}, {S_STX,  zpy}, {S_STAX, zpy},
+  {S_TYA, impl}, {S_STA, absy}, {S_TXS, impl}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_STA, absx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+
+  {S_LDY,  imm}, {S_LDA, indx}, {S_LDX,  imm}, {S_LDAX,indy},
+  {S_LDY,   zp}, {S_LDA,   zp}, {S_LDX,   zp}, {S_LDAX,  zp},
+  {S_TAY, impl}, {S_LDA,  imm}, {S_TAX, impl}, {S_ILLEGAL,0},
+  {S_LDY, abso}, {S_LDA, abso}, {S_LDX, abso}, {S_LDAX,abso},
+  {S_BCS,  rel}, {S_LDA, indy}, {S_ILLEGAL,0}, {S_LDAX,indy},
+  {S_LDY,  zpx}, {S_LDA,  zpx}, {S_LDX,  zpy}, {S_LDAX, zpy},
+  {S_CLV, impl}, {S_LDA, absy}, {S_TSX, impl}, {S_ILLEGAL,0},
+  {S_LDY, absx}, {S_LDA, absx}, {S_LDX, absy}, {S_LDAX,absy},
+
+  {S_CPY,  imm}, {S_CMP, indx}, {S_ILLEGAL,0}, {S_DCMP,indx},
+  {S_CPY,   zp}, {S_CMP,   zp}, {S_DEC,   zp}, {S_DCMP,  zp},
+  {S_INY, impl}, {S_CMP,  imm}, {S_DEX, impl}, {S_ILLEGAL,0},
+  {S_CPY, abso}, {S_CMP, abso}, {S_DEC, abso}, {S_DCMP,abso},
+  {S_BNE,  rel}, {S_CMP, indy}, {S_ILLEGAL,0}, {S_DCMP,indy},
+  {S_ILLEGAL,0}, {S_CMP,  zpx}, {S_DEC,  zpx}, {S_DCMP, zpx},
+  {S_CLD, impl}, {S_CMP, absy}, {S_ILLEGAL,0}, {S_DCMP,absy},
+  {S_ILLEGAL,0}, {S_CMP, absx}, {S_DEC, absx}, {S_DCMP,absx},
+
+  {S_CPX,  imm}, {S_SBC, indx}, {S_ILLEGAL,0}, {S_ISBC,indx},
+  {S_CPX,   zp}, {S_SBC,   zp}, {S_INC,   zp}, {S_ISBC,  zp},
+  {S_INX, impl}, {S_SBC,  imm}, {S_NOP, impl}, {S_ILLEGAL,0},
+  {S_CPX, abso}, {S_SBC, abso}, {S_INC, abso}, {S_ISBC,abso},
+  {S_BEQ,  rel}, {S_SBC, indy}, {S_ILLEGAL,0}, {S_ISBC,indy},
+  {S_ILLEGAL,0}, {S_SBC,  zpx}, {S_INC,  zpx}, {S_ISBC, zpx},
+  {S_SED, impl}, {S_SBC, absy}, {S_ILLEGAL,0}, {S_ISBC,absy},
+  {S_ILLEGAL,0}, {S_SBC, absx}, {S_INC, absx}, {S_ISBC,absx},
+};
+
+/*\
+ * The following is the officially documented
+ * MOS 6502 instruction set.
+\*/
+
+opcodes standard_nmos6502[] =
+{
+  {S_BRK, impl}, {S_ORA, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_ORA,   zp}, {S_ASL,   zp}, {S_ILLEGAL,0},
+  {S_PHP, impl}, {S_ORA,  imm}, {S_ASL, accu}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_ORA, abso}, {S_ASL, abso}, {S_ILLEGAL,0},
+  {S_BPL,  rel}, {S_ORA, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_ORA,  zpx}, {S_ASL,  zpx}, {S_ILLEGAL,0},
+  {S_CLC, impl}, {S_ORA, absy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_ORA, absx}, {S_ASL, absx}, {S_ILLEGAL,0},
+
+  {S_JSR, abso}, {S_AND, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_BIT,   zp}, {S_AND,   zp}, {S_ROL,   zp}, {S_ILLEGAL,0},
+  {S_PLP, impl}, {S_AND,  imm}, {S_ROL, accu}, {S_ILLEGAL,0},
+  {S_BIT, abso}, {S_AND, abso}, {S_ROL, abso}, {S_ILLEGAL,0},
+  {S_BMI,  rel}, {S_AND, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_AND,  zpx}, {S_ROL,  zpx}, {S_ILLEGAL,0},
+  {S_SEC, impl}, {S_AND, absy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_AND, absx}, {S_ROL, absx}, {S_ILLEGAL,0},
+
+  {S_RTI, impl}, {S_EOR, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_EOR,   zp}, {S_LSR,   zp}, {S_ILLEGAL,0},
+  {S_PHA, impl}, {S_EOR,  imm}, {S_LSR, accu}, {S_ILLEGAL,0},
+  {S_JMP, abso}, {S_EOR, abso}, {S_LSR, abso}, {S_ILLEGAL,0},
+  {S_BVC,  rel}, {S_EOR, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_EOR,  zpx}, {S_LSR,  zpx}, {S_ILLEGAL,0},
+  {S_CLI, impl}, {S_EOR, absy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_EOR, absx}, {S_LSR, absx}, {S_ILLEGAL,0},
+
+  {S_RTS, impl}, {S_ADC, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_ADC,   zp}, {S_ROR,   zp}, {S_ILLEGAL,0},
+  {S_PLA, impl}, {S_ADC,  imm}, {S_ROR, accu}, {S_ILLEGAL,0},
+  {S_JMP, iabs}, {S_ADC, abso}, {S_ROR, abso}, {S_ILLEGAL,0},
+  {S_BVS,  rel}, {S_ADC, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_ADC,  zpx}, {S_ROR,  zpx}, {S_ILLEGAL,0},
+  {S_SEI, impl}, {S_ADC, absy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_ADC, absx}, {S_ROR, absx}, {S_ILLEGAL,0},
+
+  {S_ILLEGAL,0}, {S_STA, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_STY,   zp}, {S_STA,   zp}, {S_STX,   zp}, {S_ILLEGAL,0},
+  {S_DEY, impl}, {S_ILLEGAL,0}, {S_TXA, impl}, {S_ILLEGAL,0},
+  {S_STY, abso}, {S_STA, abso}, {S_STX, abso}, {S_ILLEGAL,0},
+  {S_BCC,  rel}, {S_STA, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_STY,  zpx}, {S_STA,  zpx}, {S_STX,  zpy}, {S_ILLEGAL,0},
+  {S_TYA, impl}, {S_STA, absy}, {S_TXS, impl}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_STA, absx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+
+  {S_LDY,  imm}, {S_LDA, indx}, {S_LDX,  imm}, {S_ILLEGAL,0},
+  {S_LDY,   zp}, {S_LDA,   zp}, {S_LDX,   zp}, {S_ILLEGAL,0},
+  {S_TAY, impl}, {S_LDA,  imm}, {S_TAX, impl}, {S_ILLEGAL,0},
+  {S_LDY, abso}, {S_LDA, abso}, {S_LDX, abso}, {S_ILLEGAL,0},
+  {S_BCS,  rel}, {S_LDA, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_LDY,  zpx}, {S_LDA,  zpx}, {S_LDX,  zpy}, {S_ILLEGAL,0},
+  {S_CLV, impl}, {S_LDA, absy}, {S_TSX, impl}, {S_ILLEGAL,0},
+  {S_LDY, absx}, {S_LDA, absx}, {S_LDX, absy}, {S_ILLEGAL,0},
+
+  {S_CPY,  imm}, {S_CMP, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_CPY,   zp}, {S_CMP,   zp}, {S_DEC,   zp}, {S_ILLEGAL,0},
+  {S_INY, impl}, {S_CMP,  imm}, {S_DEX, impl}, {S_ILLEGAL,0},
+  {S_CPY, abso}, {S_CMP, abso}, {S_DEC, abso}, {S_ILLEGAL,0},
+  {S_BNE,  rel}, {S_CMP, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_CMP,  zpx}, {S_DEC,  zpx}, {S_ILLEGAL,0},
+  {S_CLD, impl}, {S_CMP, absy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_CMP, absx}, {S_DEC, absx}, {S_ILLEGAL,0},
+
+  {S_CPX,  imm}, {S_SBC, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_CPX,   zp}, {S_SBC,   zp}, {S_INC,   zp}, {S_ILLEGAL,0},
+  {S_INX, impl}, {S_SBC,  imm}, {S_NOP, impl}, {S_ILLEGAL,0},
+  {S_CPX, abso}, {S_SBC, abso}, {S_INC, abso}, {S_ILLEGAL,0},
+  {S_BEQ,  rel}, {S_SBC, indy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_SBC,  zpx}, {S_INC,  zpx}, {S_ILLEGAL,0},
+  {S_SED, impl}, {S_SBC, absy}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_SBC, absx}, {S_INC, absx}, {S_ILLEGAL,0},
+};
+
+
+/*\
+ * The following is the officially documented
+ * Rockwell R65C02 instruction set.
+\*/
+
+opcodes r65c02[] =
+{
+  {S_BRK, impl}, {S_ORA, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_TSB,   zp}, {S_ORA,   zp}, {S_ASL,   zp}, {S_RMB0,  zp},
+  {S_PHP, impl}, {S_ORA,  imm}, {S_ASL, accu}, {S_ILLEGAL,0},
+  {S_TSB, abso}, {S_ORA, abso}, {S_ASL, abso}, {S_BBR0,zrel},
+  {S_BPL,  rel}, {S_ORA, indy}, {S_ORA,  ind}, {S_ILLEGAL,0},
+  {S_TRB,   zp}, {S_ORA,  zpx}, {S_ASL,  zpx}, {S_RMB1,  zp},
+  {S_CLC, impl}, {S_ORA, absy}, {S_INC, accu}, {S_ILLEGAL,0},
+  {S_TRB, abso}, {S_ORA, absx}, {S_ASL, absx}, {S_BBR1,zrel},
+
+  {S_JSR, abso}, {S_AND, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_BIT,   zp}, {S_AND,   zp}, {S_ROL,   zp}, {S_RMB2,  zp},
+  {S_PLP, impl}, {S_AND,  imm}, {S_ROL, accu}, {S_ILLEGAL,0},
+  {S_BIT, abso}, {S_AND, abso}, {S_ROL, abso}, {S_BBR2,zrel},
+  {S_BMI,  rel}, {S_AND, indy}, {S_AND,  ind}, {S_ILLEGAL,0},
+  {S_BIT,  zpx}, {S_AND,  zpx}, {S_ROL,  zpx}, {S_RMB3,  zp},
+  {S_SEC, impl}, {S_AND, absy}, {S_DEC, accu}, {S_ILLEGAL,0},
+  {S_BIT, absx}, {S_AND, absx}, {S_ROL, absx}, {S_BBR3,zrel},
+
+  {S_RTI, impl}, {S_EOR, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_EOR,   zp}, {S_LSR,   zp}, {S_RMB4,  zp},
+  {S_PHA, impl}, {S_EOR,  imm}, {S_LSR, accu}, {S_ILLEGAL,0},
+  {S_JMP, abso}, {S_EOR, abso}, {S_LSR, abso}, {S_BBR4,zrel},
+  {S_BVC,  rel}, {S_EOR, indy}, {S_EOR,  ind}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_EOR,  zpx}, {S_LSR,  zpx}, {S_RMB5,  zp},
+  {S_CLI, impl}, {S_EOR, absy}, {S_PHY, impl}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_EOR, absx}, {S_LSR, absx}, {S_BBR5,zrel},
+
+  {S_RTS, impl}, {S_ADC, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_STZ,   zp}, {S_ADC,   zp}, {S_ROR,   zp}, {S_RMB6,  zp},
+  {S_PLA, impl}, {S_ADC,  imm}, {S_ROR, accu}, {S_ILLEGAL,0},
+  {S_JMP, iabs}, {S_ADC, abso}, {S_ROR, abso}, {S_BBR6,zrel},
+  {S_BVS,  rel}, {S_ADC, indy}, {S_ADC,  ind}, {S_ILLEGAL,0},
+  {S_STZ,  zpx}, {S_ADC,  zpx}, {S_ROR,  zpx}, {S_RMB7,  zp},
+  {S_SEI, impl}, {S_ADC, absy}, {S_PLY, impl}, {S_ILLEGAL,0},
+  {S_JMP,iabsx}, {S_ADC, absx}, {S_ROR, absx}, {S_BBR7,zrel},
+
+  {S_BRA,  rel}, {S_STA, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_STY,   zp}, {S_STA,   zp}, {S_STX,   zp}, {S_SMB0,  zp},
+  {S_DEY, impl}, {S_BIT,  imm}, {S_TXA, impl}, {S_ILLEGAL,0},
+  {S_STY, abso}, {S_STA, abso}, {S_STX, abso}, {S_BBS0,zrel},
+  {S_BCC,  rel}, {S_STA, indy}, {S_STA,  ind}, {S_ILLEGAL,0},
+  {S_STY,  zpx}, {S_STA,  zpx}, {S_STX,  zpy}, {S_SMB1,  zp},
+  {S_TYA, impl}, {S_STA, absy}, {S_TXS, impl}, {S_ILLEGAL,0},
+  {S_STZ, abso}, {S_STA, absx}, {S_STZ, absx}, {S_BBS1,zrel},
+
+  {S_LDY,  imm}, {S_LDA, indx}, {S_LDX,  imm}, {S_ILLEGAL,0},
+  {S_LDY,   zp}, {S_LDA,   zp}, {S_LDX,   zp}, {S_SMB2,  zp},
+  {S_TAY, impl}, {S_LDA,  imm}, {S_TAX, impl}, {S_ILLEGAL,0},
+  {S_LDY, abso}, {S_LDA, abso}, {S_LDX, abso}, {S_BBS2,zrel},
+  {S_BCS,  rel}, {S_LDA, indy}, {S_LDA,  ind}, {S_ILLEGAL,0},
+  {S_LDY,  zpx}, {S_LDA,  zpx}, {S_LDX,  zpy}, {S_SMB3,  zp},
+  {S_CLV, impl}, {S_LDA, absy}, {S_TSX, impl}, {S_ILLEGAL,0},
+  {S_LDY, absx}, {S_LDA, absx}, {S_LDX, absy}, {S_BBS3,zrel},
+
+  {S_CPY,  imm}, {S_CMP, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_CPY,   zp}, {S_CMP,   zp}, {S_DEC,   zp}, {S_SMB4,  zp},
+  {S_INY, impl}, {S_CMP,  imm}, {S_DEX, impl}, {S_ILLEGAL,0},
+  {S_CPY, abso}, {S_CMP, abso}, {S_DEC, abso}, {S_BBS4,zrel},
+  {S_BNE,  rel}, {S_CMP, indy}, {S_CMP,  ind}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_CMP,  zpx}, {S_DEC,  zpx}, {S_SMB5,  zp},
+  {S_CLD, impl}, {S_CMP, absy}, {S_PHX, impl}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_CMP, absx}, {S_DEC, absx}, {S_BBS5,zrel},
+
+  {S_CPX,  imm}, {S_SBC, indx}, {S_ILLEGAL,0}, {S_ILLEGAL,0},
+  {S_CPX,   zp}, {S_SBC,   zp}, {S_INC,   zp}, {S_SMB6,  zp},
+  {S_INX, impl}, {S_SBC,  imm}, {S_NOP, impl}, {S_ILLEGAL,0},
+  {S_CPX, abso}, {S_SBC, abso}, {S_INC, abso}, {S_BBS6,zrel},
+  {S_BEQ,  rel}, {S_SBC, indy}, {S_SBC,  ind}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_SBC,  zpx}, {S_INC,  zpx}, {S_SMB7,  zp},
+  {S_SED, impl}, {S_SBC, absy}, {S_PLX, impl}, {S_ILLEGAL,0},
+  {S_ILLEGAL,0}, {S_SBC, absx}, {S_INC, absx}, {S_BBS7,zrel},
+};
+#endif /* _MAIN_C_ */
+
+#endif /* _OPCODES_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/options.h	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,138 @@
+/*\
+ *  dxa v0.1.1 -- symbolic 65xx disassembler
+ *
+ *  Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *  Changes for dxa (C) 2005, 2006 Cameron Kaiser
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Marko does not maintain dxa, so questions specific to dxa should be
+ *  sent to me at ckaiser@floodgap.com . Otherwise,
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+/* options.h - constant definitions for program options */
+#ifndef _OPTIONS_H_
+#define _OPTIONS_H_
+
+/************** USER DEFINED SETTINGS ... you may change these **************/
+
+/* #define LONG_OPTIONS	*//* turn on if you want them -- needs getopt_long() */
+
+/******************* WHITE HATS ONLY BELOW THIS POINT !! ********************/
+
+#ifndef _MAIN_C_
+extern
+#endif
+unsigned int Options;
+
+/****************\
+* OUTPUT OPTIONS *
+\****************/
+
+#define M_ADDRESSES   12 /* ADDRESS INFORMATION PRODUCTION */
+#define O_ADR_NOTHING 0  /* do not include addresses in the output */
+#define O_ADR_ADRPFIX 8  /* begin each line with its assembling address */
+#define O_ADR_ADR_DMP 12 /* begin each line with a hexadecimal dump of
+                            its address and the bytes it contains */
+
+                         /* LABEL INFORMATION PRODUCTION */
+#define B_LBL_NO_EXT  0  /* do not produce labels for referred
+                            addresses outside the program's area */
+#define B_LBL_ALWAYS  16 /* substitute all found address references
+                            with label references */
+
+#define M_ADR_TABLES  96 /* ADDRESS TABLE DETECTION */
+#define O_TBL_IGNORE  0  /* do not detect any address tables */
+#define O_TBL_DETECT  32 /* detect address tables and provide them
+                            with label statements */
+#define O_TBL_NOEXT   64 /* detect only addresses that belong to
+                            the program file */
+
+                         /* ADDRESS STATEMENT INTERPRETATION */
+#define B_STM_IGNORE  0  /* do not detect or interpret statements
+                            like lda #<label */
+#define B_STM_DETECT  128 /* provide load instructions with label
+                            statements when possible*/
+
+			/* TAB OR COLON */
+#define B_LABTAB	0 /* use tabs to separate labels from text */
+#define B_LABCOL	262144 /* use colon and newline */
+
+/********************\
+* PROCESSING OPTIONS *
+\********************/
+
+			  /* STARTING ADDRESS */
+#define B_SA_WORD     65536 /* write the starting address as .word to file */
+#define B_SA_NO_WORD  0   /* ... or don't */
+#define B_GET_SA	131072 /* read the first 2 bytes as starting address */
+#define B_NO_GET_SA	0	/* ... or expect them on the command line */
+
+                          /* CUSTOM STACK HANDLING COMPATIBILITY */
+#define B_STK_SUSPECT 0   /* assume that a JSR might not return to the
+                             following address; mark the routines
+                             following a JSR as "potential". */
+#define B_STK_BALANCE 256 /* expect the rest of the routine following
+                             a JSR to be valid */
+
+                          /* ROUTINE DETECTION */
+#define B_RSC_LOUSE   0   /* all routines that consist of plain single-byte
+                             instruction (e.g. RTI or RTS) are valid */
+#define B_RSC_STRICT  512 /* routines found by scanning remaining
+                             unprocessed bytes must consist of more
+                             than one instruction to be valid */
+
+#define M_DATA_BLOCKS 3072 /* DATA BLOCK DETECTION */
+#define O_DBL_IGNORE  0    /* list the whole file as a program; dump hex
+                              only if the area is marked as a data block */
+#define O_DBL_DETECT  1024 /* if a "suspected" routine contains invalid
+                              code or jumps to any routine that leads to
+                              any routine containing invalid code, the
+                              start byte of it is marked to be data */
+#define O_DBL_NOSCAN  2048 /* skip the scanning in the fourth phase (3.4):
+                              list as data all the bytes that have remained
+                              unprocessed in the previous phases */
+#define O_DBL_STRICT  3072 /* if a "sure" routine contains illegal code,
+                              exit the unassembling process immediately */
+
+                           /* IMPROVED DATA BLOCK DETECTION */
+#define B_JMP_LOUSE   0    /* `stupid' jumps cause only warnings to the
+                              output listing */
+#define B_JMP_STRICT  4096 /* valid routines may not contain unreasonable
+                              branches or jumps like `BNE *' (D0 FE),
+                              `JMP *' or `JSR *' */
+#define B_BRK_ACCEPT  0    /* a BRK or STP is considered to mark the end of
+                              a routine */
+#define B_BRK_REJECT  8192 /* any routine that contains a BRK or an STP is
+                               invalid */
+
+#define B_SCEPTIC    16384 /* determines if the program should suspect also
+                              the target addresses of relative branches */
+
+#define B_CROSSREF   32768 /* determines if a cross-reference should
+                              be created */
+
+#endif /* _OPTIONS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/proto.h	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,72 @@
+/*\
+ *  dxa v0.1.1 -- symbolic 65xx disassembler
+ *
+ *  Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+#include "structures.h"
+
+#ifdef __STDC__
+#define PROTO(x) x
+#else
+#define PROTO(x) ()
+#endif
+
+/* scan.c */
+
+int ScanSpecified PROTO((void));   /* scan all "sure" routines */
+void ScanPotentials PROTO((void)); /* scan the "potential" routines */
+void ScanTheRest PROTO((void));    /* scan unprocessed memory places
+                                      for routines */
+
+/* table.c */
+
+table *FindNextEntryType PROTO((table *entry, unsigned char andmask,
+                                unsigned char eormask));
+table *FindNextEntryTypeParent PROTO((table *entry, ADDR_T parent,
+                                      unsigned char andmask,
+                                      unsigned char eormask));
+table *FindNextEntry PROTO((table *entry, ADDR_T address,
+                            unsigned char andmask, unsigned char eormask));
+void AddEntry PROTO((ADDR_T address, ADDR_T parent, unsigned char type));
+void DeleteEntry PROTO((table *entry));
+
+/* label.c */
+
+void AddLabel PROTO((ADDR_T address, char *name));
+char *Label PROTO((ADDR_T address, int admode));
+void Collect PROTO((void)); /* garbage collection */
+
+/* vector.c */
+
+void SearchVectors PROTO((void));
+ADDR_T WordTableEnd PROTO((ADDR_T Start));
+
+/* dump.c */
+
+void Dump PROTO((void)); /* dump the program */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scan.c	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,920 @@
+/*\
+ *  dxa v0.1.1 -- symbolic 65xx disassembler
+ *
+ *  Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+#define _SCAN_C_
+#include <stdio.h>
+#include "proto.h"
+#include "opcodes.h"
+#include "options.h"
+
+int ScanSure PROTO((ADDR_T scanstart));
+int ScanPotential PROTO((ADDR_T scanstart));
+void UnDoScan PROTO((ADDR_T scanstart));
+void DeleteSuspectedParents PROTO((ADDR_T child));
+
+#ifndef __STDC__
+int
+ScanSure (scanstart)
+     ADDR_T scanstart;
+#else
+int ScanSure (ADDR_T scanstart)
+#endif
+{
+  ADDR_T address, addr;
+  opcodes *instr;
+
+  unsigned int size, counter;
+
+  for (address = scanstart;; address += size) {
+    if (GetMemFlag (address)) /* rest of routine not valid */
+      return ((Options & M_DATA_BLOCKS) == O_DBL_STRICT);
+
+    instr = &opset[Memory[address]];
+
+    if (!instr->mnemonic) /* invalid opcode */
+      return ((Options & M_DATA_BLOCKS) == O_DBL_STRICT);
+
+    size = sizes[instr->admode];
+    if ((ADDR_T)(address + size - StartAddress) >
+        (ADDR_T)(EndAddress - StartAddress))
+      break; /* end of program code encountered */
+
+    switch (GetMemType (address)) {
+    case MEM_INSTRUCTION:
+      return 0; /* The rest of the routine has already been processed. */
+
+    case MEM_DATA:
+      AddEntry (address, scanstart, WRN_INSTR_WRITTEN_TO);
+      break;
+
+    case MEM_PARAMETER:
+      AddEntry (address, scanstart, WRN_PARAM_JUMPED_TO);
+    }
+
+    SetMemType (address, MEM_INSTRUCTION);
+
+    for (counter = size, addr = address + 1; --counter; addr++)
+      switch GetMemType(addr) {
+      case MEM_INSTRUCTION:
+        AddEntry (addr, scanstart, WRN_PARAM_JUMPED_TO);
+        break;
+      case MEM_DATA:
+        AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO);
+        /* fall through */
+      default:
+        SetMemType (addr, MEM_PARAMETER);
+      }
+
+    if (instr->admode == zrel) {
+      addr = Memory[(ADDR_T)(address + 1)];
+
+      if (GetMemFlag (addr) && GetMemType (addr) == MEM_UNPROCESSED)
+	return (Options & M_DATA_BLOCKS) == O_DBL_STRICT;
+
+      if (((ADDR_T)(addr - StartAddress) <
+	   (ADDR_T)(EndAddress - StartAddress) ||
+	   Options & B_LBL_ALWAYS)) {
+	PutLabel (addr);
+	PutLowByte (addr);
+	PutHighByte (addr);
+      }
+
+      addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 2)] +
+		      address + size);
+      goto IsJump;
+    }
+
+    if (instr->admode == rel) {
+      addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 1)] +
+                      address + size);
+
+      goto IsJump;
+    }
+    if ((instr->mnemonic == S_JSR || instr->mnemonic == S_JMP) &&
+        instr->admode == abso) {
+      addr = Memory[(ADDR_T)(address + 1)] +
+        (Memory[(ADDR_T)(address + 2)] << 8);
+
+    IsJump:
+      if (GetMemFlag (addr))
+        return ((Options & M_DATA_BLOCKS) == O_DBL_STRICT);
+
+      if ((ADDR_T)(addr - StartAddress) <
+          (ADDR_T)(EndAddress - StartAddress)) {
+        if (GetMemType (addr) == MEM_INSTRUCTION) {
+          PutLabel (addr);
+          PutLowByte (addr);
+          PutHighByte (addr);
+        }
+        else
+          AddEntry (addr, scanstart, Options & B_SCEPTIC &&
+                    instr->admode == rel && instr->mnemonic != S_BRA ?
+                    RTN_POTENTIAL : RTN_SURE);
+      }
+      else if (Options & B_LBL_ALWAYS) {
+        PutLabel (addr);
+        PutLowByte (addr);
+        PutHighByte (addr);
+      }
+
+      if ((Options & M_DATA_BLOCKS) == O_DBL_STRICT &&
+	  Options & B_JMP_STRICT &&
+	  addr == address && instr->mnemonic != S_BVC)
+        return 1;
+    }
+
+    switch (instr->mnemonic) {
+    case S_JMP:
+      addr = Memory[(ADDR_T)(address + 1)] +
+	(Memory[(ADDR_T)(address + 2)] << 8);
+
+      if (instr->admode == iabs && (ADDR_T)(addr - StartAddress) <
+	  (ADDR_T)(EndAddress - StartAddress)) {
+	PutLabel (addr);
+	PutLowByte (addr);
+	PutHighByte (addr);
+
+	/* Mark pointer as data. */
+	switch (GetMemType (addr)) {
+	case MEM_UNPROCESSED:
+	  SetMemType (addr, MEM_DATA);
+	  break;
+	case MEM_INSTRUCTION:
+	  AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO);
+	  break;
+	case MEM_PARAMETER:
+	  AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO);
+	  break;
+	}
+
+	addr++;
+
+	if ((ADDR_T)(addr - StartAddress) <
+	    (ADDR_T)(EndAddress - StartAddress))
+	  switch (GetMemType (addr)) {
+	  case MEM_UNPROCESSED:
+	    SetMemType (addr, MEM_DATA);
+	    break;
+	  case MEM_INSTRUCTION:
+	    AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO);
+	    break;
+	  case MEM_PARAMETER:
+	    AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO);
+	    break;
+	  }
+      }
+      else if (Options & B_LBL_ALWAYS) {
+	PutLabel (addr);
+	PutLowByte (addr);
+	PutHighByte (addr);
+      }
+    case S_BRA:
+    case S_RTS:
+    case S_RTI:
+      return 0;
+
+    case S_BRK:
+    case S_STP:
+      return (Options & M_DATA_BLOCKS) == O_DBL_STRICT &&
+	Options & B_BRK_REJECT;
+    }
+
+    if (instr->admode == rel) {
+      if ((ADDR_T)(addr - scanstart) >= (ADDR_T)(address - scanstart)
+          || GetMemType (addr) != MEM_INSTRUCTION) {
+        if (GetMemType (address + size) != MEM_INSTRUCTION)
+          AddEntry (address + size, scanstart, RTN_POTENTIAL);
+
+        return 0;
+      }
+
+      continue;
+    }
+
+    if (instr->mnemonic == S_JSR) {
+      if (!(Options & B_STK_BALANCE)) {
+        if (GetMemType (address + size) != MEM_INSTRUCTION)
+          AddEntry (address + size, scanstart, RTN_POTENTIAL);
+
+        return 0;
+      }
+
+      continue;
+    }
+
+    switch (size) {
+    case 2:
+      addr = Memory[(ADDR_T)(address + 1)];
+      break;
+    case 3:
+      addr = Memory[(ADDR_T)(address + 1)] +
+        (Memory[(ADDR_T)(address + 2)] << 8);
+      break;
+    }
+
+    if (types[instr->admode] != impimm && GetMemFlag (addr) &&
+	GetMemType (addr) == MEM_UNPROCESSED)
+      return (Options & M_DATA_BLOCKS) == O_DBL_STRICT;
+
+    if (types[instr->admode] != impimm &&
+        ((ADDR_T)(addr - StartAddress) <
+        (ADDR_T)(EndAddress - StartAddress) ||
+        Options & B_LBL_ALWAYS)) {
+      PutLabel (addr);
+      PutLowByte (addr);
+      PutHighByte (addr);
+    }
+
+    if (types[instr->admode] != other && types[instr->admode] != impimm) {
+      if ((ADDR_T)(addr - StartAddress) <
+          (ADDR_T)(EndAddress - StartAddress)) {
+        switch (GetMemType (addr)) {
+        case MEM_UNPROCESSED:
+          SetMemType (addr, MEM_DATA);
+          break;
+        case MEM_INSTRUCTION:
+          AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO);
+          break;
+        case MEM_PARAMETER:
+          AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO);
+          break;
+        }
+
+        if (types[instr->admode] == absindir) { /* indirect mode */
+          addr++; /* set flags for upper vector byte */
+
+          if ((ADDR_T)(addr - StartAddress) <
+              (ADDR_T)(EndAddress - StartAddress))
+            switch (GetMemType (addr)) {
+            case MEM_UNPROCESSED:
+              SetMemType (addr, MEM_DATA);
+              break;
+            case MEM_INSTRUCTION:
+              AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO);
+              break;
+            case MEM_PARAMETER:
+              AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO);
+              break;
+            }
+        }
+      }
+    }
+  }
+
+  /* end of program (unexpectedly) encountered */
+
+  if (Options & O_DBL_STRICT) return 1;
+
+  AddEntry (EndAddress, scanstart, WRN_RTN_TRUNCATED);
+  return 0;
+}
+
+#ifndef __STDC__
+int
+ScanPotential (scanstart)
+     ADDR_T scanstart;
+#else
+int ScanPotential (ADDR_T scanstart)
+#endif
+{
+  ADDR_T address, addr;
+  opcodes *instr;
+
+  unsigned int size, counter;
+
+  for (address = scanstart;; address += size) {
+    if (GetMemFlag (address)) /* rest of routine not valid */
+      return 1;
+
+    instr = &opset[Memory[address]];
+
+    if (!instr->mnemonic) { /* invalid opcode */
+      SetMemFlag (address);
+
+      if (GetMemType (address) == MEM_UNPROCESSED)
+        SetMemType (address, MEM_DATA);
+      return 1;
+    }
+
+    size = sizes[instr->admode];
+    if ((ADDR_T)(address + size - StartAddress) >
+        (ADDR_T)(EndAddress - StartAddress))
+      break; /* end of program code encountered */
+
+    if (GetMemType (address) == MEM_INSTRUCTION)
+      return 0; /* The rest of the routine has already been processed. */
+
+    if (instr->admode == zrel) {
+      addr = Memory[(ADDR_T)(address + 1)];
+
+      if (GetMemFlag (addr) && GetMemType (addr) == MEM_UNPROCESSED)
+	goto Failure;
+
+      if (((ADDR_T)(addr - StartAddress) <
+	   (ADDR_T)(EndAddress - StartAddress) ||
+	   Options & B_LBL_ALWAYS))
+	AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY);
+
+      addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 1)] +
+                      address + size);
+
+      goto IsJump;
+    }
+
+    if (instr->admode == rel) {
+      addr = (ADDR_T)((int)(char)Memory[(ADDR_T)(address + 1)] +
+                      address + size);
+
+      goto IsJump;
+    }
+
+    switch (size) {
+    case 2:
+      addr = Memory[(ADDR_T)(address + 1)];
+      break;
+    case 3:
+      addr = Memory[(ADDR_T)(address + 1)] +
+        (Memory[(ADDR_T)(address + 2)] << 8);
+      break;
+    default:
+      addr = address;
+    }
+
+    if (types[instr->admode] != impimm && GetMemFlag (addr) &&
+        GetMemType (addr) == MEM_UNPROCESSED) {
+    Failure:
+      SetMemFlag (address);
+
+      if (GetMemType (address) == MEM_UNPROCESSED)
+        SetMemType (address, MEM_DATA);
+      return 1;
+    }
+
+    if ((instr->mnemonic == S_JSR || instr->mnemonic == S_JMP) &&
+        instr->admode == abso) {
+    IsJump:
+      if (GetMemFlag (addr)) {
+        SetMemFlag (address);
+
+        if (GetMemType (address) == MEM_UNPROCESSED)
+          SetMemType (address, MEM_DATA);
+        return 1;
+      }
+
+      if ((ADDR_T)(addr - StartAddress) <
+          (ADDR_T)(EndAddress - StartAddress))
+        AddEntry (addr, scanstart, Options & B_SCEPTIC &&
+                  instr->admode == rel && instr->mnemonic != S_BRA ?
+                  RTN_SUSP_POT : RTN_SUSPECTED);
+      else if (Options & B_LBL_ALWAYS)
+        AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY);
+
+      if (Options & B_JMP_STRICT && addr == address &&
+          instr->mnemonic != S_BVC) {
+        SetMemFlag (address);
+
+        if (GetMemType (address) == MEM_UNPROCESSED)
+          SetMemType (address, MEM_DATA);
+        return 1;
+      }
+    }
+
+    switch (instr->mnemonic) {
+    case S_BRK:
+    case S_STP:
+      if (Options & B_BRK_REJECT) {
+        SetMemFlag (address);
+
+        if (GetMemType (address) == MEM_UNPROCESSED)
+          SetMemType (address, MEM_DATA);
+        return 1;
+      }
+    }
+
+    if (!GetMemFlag (address))
+      switch (GetMemType (address)) {
+      case MEM_DATA:
+        AddEntry (address, scanstart, WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY);
+        break;
+
+      case MEM_PARAMETER:
+        AddEntry (address, scanstart, WRN_PARAM_JUMPED_TO | WRN_B_TEMPORARY);
+      }
+
+    SetMemType (address, MEM_INSTRUCTION);
+
+    for (counter = size, addr = address + 1; --counter; addr++)
+      switch (GetMemType (addr)) {
+      case MEM_INSTRUCTION:
+        AddEntry (addr, scanstart, WRN_PARAM_JUMPED_TO | WRN_B_TEMPORARY);
+        break;
+      case MEM_DATA:
+        if (!GetMemFlag (addr))
+          AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY);
+        break;
+      default:
+        SetMemType (addr, MEM_PARAMETER);
+      }
+
+    switch (instr->mnemonic) {
+    case S_BRK:
+    case S_STP:
+    case S_RTS:
+    case S_BRA:
+    case S_RTI:
+      return 0;
+
+    case S_JMP:
+      addr = Memory[(ADDR_T)(address + 1)] +
+	(Memory[(ADDR_T)(address + 2)] << 8);
+
+      if (instr->admode == iabs && (ADDR_T)(addr - StartAddress) <
+	  (ADDR_T)(EndAddress - StartAddress)) {
+	AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY);
+
+	/* Mark pointer as data. */
+	switch (GetMemType (addr)) {
+	case MEM_UNPROCESSED:
+	  AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY);
+	  break;
+	case MEM_INSTRUCTION:
+	  AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY);
+	  break;
+	case MEM_PARAMETER:
+	  AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY);
+	  break;
+	}
+
+	addr++;
+
+	if ((ADDR_T)(addr - StartAddress) <
+	    (ADDR_T)(EndAddress - StartAddress))
+	  switch (GetMemType (addr)) {
+	  case MEM_UNPROCESSED:
+	    AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY);
+	    break;
+	  case MEM_INSTRUCTION:
+	    AddEntry (addr, scanstart,
+		      WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY);
+	    break;
+	  case MEM_PARAMETER:
+	    AddEntry (addr, scanstart,
+		      WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY);
+	    break;
+	  }
+      }
+      else if (Options & B_LBL_ALWAYS)
+	AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY);
+
+      return 0;
+    }
+
+    if (instr->admode == rel &&
+        GetMemType (address + size) != MEM_INSTRUCTION) {
+      AddEntry (address + size, scanstart, RTN_SUSP_POT);
+
+      return 0;
+    }
+
+    if (instr->mnemonic == S_JSR) {
+      if (!(Options & B_STK_BALANCE)) {
+        if (GetMemType (address + size) != MEM_INSTRUCTION)
+          AddEntry (address + size, scanstart, RTN_SUSP_POT);
+
+        return 0;
+      }
+
+      continue;
+    }
+
+    switch (size) {
+    case 2:
+      addr = Memory[(ADDR_T)(address + 1)];
+      break;
+    case 3:
+      addr = Memory[(ADDR_T)(address + 1)] +
+        (Memory[(ADDR_T)(address + 2)] << 8);
+      break;
+    }
+
+    if (types[instr->admode] != impimm &&
+        ((ADDR_T)(addr - StartAddress) <
+        (ADDR_T)(EndAddress - StartAddress) ||
+        Options & B_LBL_ALWAYS))
+      AddEntry (addr, scanstart, WRN_I_LABEL_NEEDED | WRN_B_TEMPORARY);
+
+    if (types[instr->admode] != other && types[instr->admode] != impimm) {
+      if ((ADDR_T)(addr - StartAddress) <
+          (ADDR_T)(EndAddress - StartAddress)) {
+        switch (GetMemType (addr)) {
+        case MEM_UNPROCESSED:
+          AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY);
+          break;
+        case MEM_INSTRUCTION:
+          AddEntry (addr, scanstart, WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY);
+          break;
+        case MEM_PARAMETER:
+          AddEntry (addr, scanstart, WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY);
+          break;
+        }
+
+        if (types[instr->admode] == absindir) { /* indirect mode */
+          addr++; /* set flags for upper vector byte */
+
+          if ((ADDR_T)(addr - StartAddress) <
+              (ADDR_T)(EndAddress - StartAddress))
+            switch (GetMemType (addr)) {
+            case MEM_UNPROCESSED:
+              AddEntry (addr, scanstart, WRN_I_ACCESSED | WRN_B_TEMPORARY);
+              break;
+            case MEM_INSTRUCTION:
+              AddEntry (addr, scanstart,
+                        WRN_INSTR_WRITTEN_TO | WRN_B_TEMPORARY);
+              break;
+            case MEM_PARAMETER:
+              AddEntry (addr, scanstart,
+                        WRN_PARAM_WRITTEN_TO | WRN_B_TEMPORARY);
+              break;
+            }
+        }
+      }
+    }
+  }
+
+  /* end of program (unexpectedly) encountered */
+
+  return 1;
+}
+
+#ifndef __STDC__
+int
+ScanSpecified ()
+#else
+int ScanSpecified (void)
+#endif
+{
+  table *entry;
+
+  if (fVerbose)
+    fprintf (stderr, "%s: scanning the routines at specified address(es)",
+             prog);
+
+  while ((entry = FindNextEntryType (NULL, ~0, RTN_SURE))) {
+    PutLabel (entry->address);
+    PutLowByte (entry->address);
+    PutHighByte (entry->address);
+
+    if (ScanSure (entry->address)) {
+		fprintf(stderr,"For routine specified at %i:",
+			(unsigned int)entry->address);
+		return 1;
+	}
+    DeleteEntry (entry);
+  }
+
+  return 0;
+}
+
+#ifndef __STDC__
+void
+UnDoScan (scanstart)
+     ADDR_T scanstart;
+#else
+void UnDoScan (ADDR_T scanstart)
+#endif
+{
+  opcodes *instr;
+  unsigned counter;
+  ADDR_T address;
+
+  for (address = scanstart; address != EndAddress; address++) {
+    if (GetMemFlag (address)) return;
+
+    switch (GetMemType (address)) {
+    case MEM_UNPROCESSED:
+      return;
+
+    case MEM_INSTRUCTION:
+      SetMemFlag (address);
+      SetMemType (address, MEM_DATA); /* This could cause WRN_PARAM_WRITTEN_TO
+					 in vain. */
+      instr = &opset[Memory[address++]];
+      for (counter = sizes[instr->admode]; --counter; address++)
+        if (GetMemType (address) == MEM_PARAMETER)
+          SetMemType (address, MEM_UNPROCESSED);
+        else if (GetMemType (address) == MEM_INSTRUCTION)
+          break;
+
+      if (instr->mnemonic == S_STP || instr->mnemonic == S_BRK ||
+          instr->mnemonic == S_RTI || instr->mnemonic == S_RTS ||
+          instr->mnemonic == S_JMP || instr->admode == rel)
+        return;
+
+      address--;
+      break;
+
+    case MEM_PARAMETER:
+      SetMemType (address, MEM_UNPROCESSED);
+    }
+  }
+}
+
+#ifndef __STDC__
+void
+DeleteSuspectedParents (child)
+     ADDR_T child;
+#else
+void DeleteSuspectedParents (ADDR_T child)
+#endif
+{
+  table *entry = NULL;
+
+  while ((entry = FindNextEntry (entry, child, ~(RTN_B_PROCESSED |
+                                                 RTN_B_TEMPORARY),
+                                 RTN_SUSPECTED))) {
+    if (entry->type & RTN_B_PROCESSED && entry->parent != child)
+      DeleteSuspectedParents (entry->parent);
+
+    DeleteEntry (entry);
+  }
+
+  entry = NULL;
+
+  while ((entry = FindNextEntryTypeParent (entry, child, ~0, RTN_SUSP_POT)))
+    DeleteEntry (entry);
+
+  entry = NULL;
+
+  while ((entry = FindNextEntryTypeParent (entry, child,
+                                           MASK_ANY | WRN_B_TEMPORARY,
+                                           WRN_ANY | WRN_B_TEMPORARY))) {
+    if (entry->type == (WRN_PARAM_JUMPED_TO | WRN_B_TEMPORARY))
+      SetMemType (entry->address, MEM_PARAMETER);
+
+    DeleteEntry (entry);
+  }
+
+  UnDoScan (child);
+}
+
+#ifndef __STDC__
+void
+ScanPotentials ()
+#else
+void ScanPotentials (void)
+#endif
+{
+  table *entry;
+  ADDR_T address;
+
+  if (fVerbose)
+    fprintf (stderr, "\n%s: scanning potential routines\n", prog);
+
+  while ((entry = FindNextEntryType (NULL, ~0, RTN_POTENTIAL))) {
+    address = entry->address;
+    DeleteEntry (entry);
+
+    if (!ScanPotential (address)) {
+      while ((entry = FindNextEntryType (NULL, ~RTN_B_TEMPORARY,
+                                         RTN_SUSPECTED))) {
+        entry->type |= RTN_B_PROCESSED;
+
+        if (ScanPotential (entry->address) &&
+            (Options & M_DATA_BLOCKS) != O_DBL_IGNORE) {
+          DeleteSuspectedParents (entry->address);
+          SetMemType (address, MEM_DATA);
+        }
+      }
+
+      if (GetMemType (address) != MEM_DATA) {
+        PutLabel (address);
+        PutLowByte (address);
+        PutHighByte (address);
+      }
+
+      entry = NULL;
+
+      while ((entry = FindNextEntryType (entry, ~0, RTN_B_TEMPORARY |
+                                         RTN_SUSPECTED | RTN_B_PROCESSED)))
+        DeleteEntry (entry);
+
+      entry = NULL;
+
+      while ((entry = FindNextEntryType (entry, ~0,
+                                         RTN_SUSPECTED | RTN_B_PROCESSED))) {
+        PutLabel (entry->address);
+        PutLowByte (entry->address);
+        PutHighByte (entry->address);
+        DeleteEntry (entry);
+      }
+
+      entry = NULL;
+
+      while ((entry = FindNextEntryType (entry, ~0, RTN_SUSP_POT)))
+        entry->type = RTN_POTENTIAL;
+
+      entry = NULL;
+
+      while ((entry = FindNextEntryType (entry, MASK_ANY | WRN_B_TEMPORARY,
+                                         WRN_ANY | WRN_B_TEMPORARY))) {
+        switch (entry->type & ~WRN_B_TEMPORARY) {
+        case WRN_PARAM_WRITTEN_TO:
+          if (GetMemType (entry->address) == MEM_DATA)
+            SetMemType (entry->address, MEM_PARAMETER);
+          entry->type &= ~WRN_B_TEMPORARY;
+          break;
+
+        case WRN_INSTR_WRITTEN_TO:
+          if (GetMemType (entry->address) == MEM_DATA)
+            SetMemType (entry->address, MEM_INSTRUCTION);
+          entry->type &= ~WRN_B_TEMPORARY;
+          break;
+
+        case WRN_I_ACCESSED:
+          SetMemType (entry->address, MEM_DATA);
+          /* fall through */
+        case WRN_I_LABEL_NEEDED:
+          PutLabel (entry->address);
+          PutLowByte (entry->address);
+          PutHighByte (entry->address);
+          DeleteEntry (entry);
+          break;
+
+        default:
+          entry->type &= ~WRN_B_TEMPORARY;
+        }
+      }
+    }
+    else {
+      DeleteSuspectedParents (address);
+      SetMemType (address, MEM_DATA);
+    }
+  }
+}
+
+#ifndef __STDC__
+void
+ScanTheRest ()
+#else
+void ScanTheRest (void)
+#endif
+{
+  ADDR_T address;
+  table *entry;
+  unsigned int fPotentials;
+
+  if ((Options & M_DATA_BLOCKS) == O_DBL_NOSCAN) {
+    for (address = StartAddress; address != EndAddress; address++)
+      if (GetMemType (address) == MEM_UNPROCESSED)
+        SetMemType (address, MEM_DATA);
+
+    return;
+  }
+
+  if (fVerbose)
+    fprintf (stderr, "%s: scanning the remaining bytes for routines\n", prog);
+
+  for (address = StartAddress; address != EndAddress; address++) {
+    if (GetMemType (address) || GetMemFlag (address))
+      continue; /* scan only unprocessed bytes */
+
+    if (Options & B_RSC_STRICT)
+      switch (opset[Memory[address]].mnemonic) {
+      case S_RTI:
+      case S_RTS:
+      case S_BRK:
+      case S_STP:
+        continue;
+
+      case S_BRA:
+        break;
+
+      default:
+        if (opset[Memory[address]].admode == rel &&
+            GetMemType (address + sizes[rel]) != MEM_INSTRUCTION)
+          AddEntry (address + sizes[rel], address,
+                    RTN_SUSPECTED | RTN_B_TEMPORARY);
+      }
+
+    if (fVerbose)
+      fprintf (stderr, "\r%s: scanning at %X", prog, address);
+
+    if (!ScanPotential (address)) {
+      while ((entry = FindNextEntryType (NULL, ~RTN_B_TEMPORARY,
+                                         RTN_SUSPECTED))) {
+        entry->type |= RTN_B_PROCESSED;
+
+        if (ScanPotential (entry->address) &&
+            (Options & M_DATA_BLOCKS) != O_DBL_IGNORE) {
+          DeleteSuspectedParents (entry->address);
+          SetMemType (address, MEM_DATA);
+        }
+      }
+
+      if (GetMemType (address) != MEM_DATA) {
+        PutLabel (address);
+        PutLowByte (address);
+        PutHighByte (address);
+      }
+
+      fPotentials = FALSE;
+      entry = NULL;
+
+      while ((entry = FindNextEntryType (entry, ~0, RTN_SUSP_POT))) {
+        fPotentials = TRUE;
+        entry->type = RTN_POTENTIAL;
+      }
+
+      entry = NULL;
+
+      while ((entry = FindNextEntryType (entry, ~0, RTN_B_TEMPORARY |
+                                         RTN_SUSPECTED | RTN_B_PROCESSED)))
+        DeleteEntry (entry);
+
+      entry = NULL;
+
+      while ((entry = FindNextEntryType (entry, ~0,
+                                         RTN_SUSPECTED | RTN_B_PROCESSED))) {
+        PutLabel (entry->address);
+        PutLowByte (entry->address);
+        PutHighByte (entry->address);
+        DeleteEntry (entry);
+      }
+
+      entry = NULL;
+
+      while ((entry = FindNextEntryType (entry, MASK_ANY | WRN_B_TEMPORARY,
+                                         WRN_ANY | WRN_B_TEMPORARY))) {
+        switch (entry->type & ~WRN_B_TEMPORARY) {
+        case WRN_PARAM_WRITTEN_TO:
+          if (GetMemType (entry->address) == MEM_DATA)
+            SetMemType (entry->address, MEM_PARAMETER);
+          entry->type &= ~WRN_B_TEMPORARY;
+          break;
+
+        case WRN_INSTR_WRITTEN_TO:
+          if (GetMemType (entry->address) == MEM_DATA)
+            SetMemType (entry->address, MEM_INSTRUCTION);
+          entry->type &= ~WRN_B_TEMPORARY;
+          break;
+
+        case WRN_I_ACCESSED:
+          SetMemType (entry->address, MEM_DATA);
+          /* fall through */
+        case WRN_I_LABEL_NEEDED:
+          PutLabel (entry->address);
+          PutLowByte (entry->address);
+          PutHighByte (entry->address);
+          DeleteEntry (entry);
+          break;
+
+        default:
+          entry->type &= ~WRN_B_TEMPORARY;
+        }
+      }
+
+      if (fPotentials) ScanPotentials ();
+    }
+    else {
+      DeleteSuspectedParents (address);
+      SetMemType (address, MEM_DATA);
+    }
+  }
+
+  if (fVerbose)
+    fprintf (stderr, "\n");
+
+  for (address = StartAddress; address != EndAddress; address++)
+    if (GetMemType (address) == MEM_UNPROCESSED) {
+      fPotentials = GetMemFlag (address) ? MEM_PARAMETER : MEM_DATA;
+      SetMemType (address, fPotentials);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/structures.h	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,246 @@
+/*\
+ *  dxa v0.1.1 -- symbolic 65xx disassembler
+ *
+ *  Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+/* structures.h - memory structures and related constants and macros */
+#ifndef _STRUCTURES_H_
+#define _STRUCTURES_H_
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE !FALSE
+#endif
+
+#ifndef NULL
+#define NULL (void *)0
+#endif
+
+#define MAXLINE 50 /* maximum amount of bytes used when reading a label in */
+
+typedef unsigned short int ADDR_T; /* 16-bit unsigned integer */
+typedef unsigned char      DATA_T; /* 8-bit unsigned integer */
+
+/********************\
+* Program code table *
+\********************/
+
+#ifndef _MAIN_C_
+extern
+#endif
+DATA_T Memory[1 << 16];
+
+/*************************\
+* Memory place type table *
+\*************************/
+
+#ifndef _MAIN_C_
+extern
+#endif
+unsigned MemType[(1 << 14) / sizeof(unsigned)];
+
+#define GetMemType(address) \
+     ((MemType[((ADDR_T)address) / (4 * sizeof *MemType)] >>    \
+       ((address % (4 * sizeof *MemType)) << 1)) & 3)
+
+#define SetMemType(address, type) \
+     (MemType[((ADDR_T)address) / (4 * sizeof *MemType)] =      \
+      (MemType[((ADDR_T)address) / (4 * sizeof *MemType)] &     \
+       ~(3 << ((address % (4 * sizeof *MemType)) << 1))) |      \
+      (type << ((address % (4 * sizeof *MemType)) << 1)))
+ 
+/* The table consists of bit pairs with the following values: */
+
+#define MEM_UNPROCESSED 0 /* the memory place has not been processed yet */
+#define MEM_INSTRUCTION 1 /* a machine language instruction starts at
+                             this memory place */
+#define MEM_DATA        2 /* the memory place contains data */
+#define MEM_PARAMETER   3 /* a parameter of a machine language
+                             instruction is at this place */
+
+/*************************\
+* Memory place flag table *
+\*************************/
+
+#ifndef _MAIN_C_
+extern
+#endif
+unsigned
+     MemFlag[(1 << 13) / sizeof(unsigned)],
+     MemLabel[(1 << 13) / sizeof(unsigned)],
+     LowByte[(1 << 8) / sizeof(unsigned)],
+     HighByte[(1 << 8) / sizeof(unsigned)];
+
+#define GetMemFlag(address) \
+     ((MemFlag[((ADDR_T)address) / (8 * sizeof *MemFlag)] >>    \
+       (address % (8 * sizeof *MemFlag))) & 1)
+
+#define SetMemFlag(address) \
+     (MemFlag[((ADDR_T)address) / (8 * sizeof *MemFlag)] |=     \
+      (1 << (address % (8 * sizeof *MemFlag))))
+
+/* The flag table indicates if there may be a valid routine at the address.
+   If a flag is set, there cannot be valid routines at the address. */
+
+#define IsLabeled(address) \
+     ((MemLabel[((ADDR_T)address) / (8 * sizeof *MemLabel)] >>  \
+       (address % (8 * sizeof *MemLabel))) & 1)
+
+#define PutLabel(address) \
+     (MemLabel[((ADDR_T)address) / (8 * sizeof *MemLabel)] |=   \
+      (1 << (address % (8 * sizeof *MemLabel))))
+
+/* These macros tell if there is a label for a given address, or cause a
+   label to be produced for an address. */
+
+#define IsLowByte(address) \
+     ((LowByte[((unsigned char)address) / (8 * sizeof *LowByte)] >>     \
+       (address % (8 * sizeof *LowByte))) & 1)
+
+#define PutLowByte(address) \
+     (LowByte[((unsigned char)address) / (8 * sizeof *LowByte)] |=      \
+      (1 << (address % (8 * sizeof *LowByte))))
+
+/* Corresponding macros for the low byte address table. */
+
+#define IsHighByte(address) \
+     ((HighByte[(address >> 8) / (8 * sizeof *HighByte)] >>     \
+       ((address >> 8) % (8 * sizeof *HighByte))) & 1)
+
+#define PutHighByte(address) \
+     (HighByte[(address >> 8) / (8 * sizeof *HighByte)] |=      \
+      (1 << ((address >> 8) % (8 * sizeof *HighByte))))
+
+/* Corresponding macros for the high byte address table. */
+
+/***************************************\
+* Routine/warning address table entries *
+\***************************************/
+
+typedef struct table
+{
+  ADDR_T address;
+  ADDR_T parent;
+  unsigned char type;
+} table;
+
+/* The table.type byte has the following format: */
+
+#define RTN_SURE        0x80 /* address must point to a valid subprogram */
+#define RTN_POTENTIAL   0x81 /* address may point to a valid subprogram (an
+                                address following a conditional branch
+                                instruction) */
+#define RTN_SUSPECTED   0x82 /* address might point to a valid subprogram
+                                (an address encountered during processing
+                                an RTN_POTENTIAL entry) */
+#define RTN_SUSP_POT    0x83 /* address might point to a subprogram (an
+                                address following a conditional branch
+                                instruction that was encountered during
+                                processing an RTN_SUSPECTED or
+                                RTN_POTENTIAL entry) */
+#define RTN_B_TEMPORARY 0x10 /* declares the entry as temporary */
+#define RTN_B_PROCESSED 0x20 /* address seems to point to a valid
+                               subprogram (a successfully processed
+                               RTN_SUSPECTED entry is
+                               RTN_SUSPECTED | RTN_B_PROCESSED) */
+
+#define MASK_ANY        0xc0 /* mask for determining the type of the entry */
+
+#define RTN_ANY         0x80 /* mask for determining if an entry is a
+                                routine or not */
+
+#define WRN_PARAM_WRITTEN_TO 0x40 /* the parameter of the instruction is
+                                     written to */
+#define WRN_INSTR_WRITTEN_TO 0x41 /* the instruction is modified by the
+                                     program */
+
+#define WRN_PARAM_JUMPED_TO  0x42 /* a jump occurs in the middle of the
+                                     instruction, e.g. BIT $01A9 */
+#define WRN_RTN_TRUNCATED    0x43 /* the routine is truncated, the rest of
+                                     the instructions are retrieved outside
+                                     the loaded file (very fatal error) */
+#define WRN_I_ACCESSED       0x44 /* not an actual warning: an unprocessed
+                                     memory place is accessed by an
+                                     RTN_POTENTIAL or RTN_SUSPECTED routine */
+#define WRN_I_LABEL_NEEDED   0x45 /* not an actual warning: a label will be
+                                     needed for this memory place */
+
+#define WRN_B_TEMPORARY      0x20 /* mask for determining whether a warning
+                                     is temporary and may be deleted later */
+
+#define WRN_ANY              0x40 /* mask for determining whether an
+                                     entry is a warning or not */
+
+#define TBL_DELETED          0    /* the entry may be reused */
+
+/*********************\
+* Label table entries *
+\*********************/
+
+typedef struct label
+{
+  ADDR_T address;
+  char *name;
+} label;
+
+/********************\
+* Word table entries *
+\********************/
+
+typedef struct words
+{
+  ADDR_T start, end;
+} words;
+
+#ifndef _MAIN_C_
+extern char *prog;
+extern ADDR_T StartAddress, EndAddress;
+extern int fVerbose;
+#else
+char *prog;
+ADDR_T StartAddress, EndAddress;
+int fVerbose = FALSE;
+#endif /* _MAIN_C_ */
+
+#ifndef _TABLE_C_
+extern unsigned int entrycount;
+extern table *scantable; /* table of all warnings generated or routines
+                            encountered */
+#else
+unsigned int entrycount = 0;
+table *scantable = NULL;
+#endif /* _TABLE_C_ */
+
+#ifndef _DUMP_C_
+extern int listwidth; /* maximum amount of bytes dumped on a source line */
+#else
+int listwidth = 0;
+#endif /* _DUMP_C_ */
+
+#endif /* _STRUCTURES_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/table.c	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,162 @@
+/*\
+ *  dxa v0.1.1 -- symbolic 65xx disassembler
+ *
+ *  Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+/* table.c */
+#define _TABLE_C_
+
+#include <stdlib.h>
+#include "proto.h"
+
+static unsigned int firstunused = 0;
+
+#ifndef __STDC__
+table *
+FindNextEntryType (entry, andmask, eormask)
+     table *entry;
+     unsigned char andmask;
+     unsigned char eormask;
+#else
+table *FindNextEntryType (table *entry, unsigned char andmask,
+                          unsigned char eormask)
+#endif
+{
+  if (!scantable) return NULL;
+
+  if (!entry || entry >= &scantable[entrycount])
+    entry = scantable;
+  else if (++entry >= &scantable[entrycount])
+    return NULL;
+
+  for (; entry < &scantable[entrycount]; entry++)
+    if (entry->type && !((entry->type & andmask) ^ eormask))
+      return entry;
+
+  return NULL;
+}
+
+#ifndef __STDC__
+table *
+FindNextEntryTypeParent (entry, parent, andmask, eormask)
+     table *entry;
+     ADDR_T parent;
+     unsigned char andmask;
+     unsigned char eormask;
+#else
+table *FindNextEntryTypeParent (table *entry, ADDR_T parent,
+                            unsigned char andmask, unsigned char eormask)
+#endif
+{
+  if (!scantable) return NULL;
+
+
+  if (!entry || entry >= &scantable[entrycount])
+    entry = scantable;
+  else if (++entry >= &scantable[entrycount])
+    return NULL;
+
+  for (; entry < &scantable[entrycount]; entry++)
+    if (entry->parent == parent && entry->type &&
+        !((entry->type & andmask) ^ eormask))
+      return entry;
+
+  return NULL;
+}
+
+#ifndef __STDC__
+table *
+FindNextEntry (entry, address, andmask, eormask)
+     table *entry;
+     ADDR_T address;
+     unsigned char andmask;
+     unsigned char eormask;
+#else
+table *FindNextEntry (table *entry, ADDR_T address,
+                      unsigned char andmask, unsigned char eormask)
+#endif
+{
+  if (!scantable) return NULL;
+
+  if (!entry || entry >= &scantable[entrycount])
+    entry = scantable;
+  else if (++entry >= &scantable[entrycount])
+    return NULL;
+
+  for (; entry < &scantable[entrycount]; entry++)
+    if (entry->address == address && entry->type &&
+        !((entry->type & andmask) ^ eormask))
+      return entry;
+
+  return NULL;
+}
+
+#ifndef __STDC__
+void
+AddEntry (address, parent, type)
+     ADDR_T address;
+     ADDR_T parent;
+     unsigned char type;
+#else
+void AddEntry (ADDR_T address, ADDR_T parent, unsigned char type)
+#endif
+{
+  if (firstunused < entrycount) {
+    scantable[firstunused].address = address;
+    scantable[firstunused].parent = parent;
+    scantable[firstunused].type = type;
+
+    while (++firstunused < entrycount && scantable[firstunused].type);
+  }
+  else {
+    scantable = scantable ?
+      realloc (scantable, (entrycount + 1) * sizeof *scantable) :
+      malloc (sizeof *scantable);
+
+    scantable[entrycount].address = address;
+    scantable[entrycount].parent = parent;
+    scantable[entrycount].type = type;
+
+    firstunused = ++entrycount;
+  }
+}
+
+#ifndef __STDC__
+void
+DeleteEntry (entry)
+     table *entry;
+#else
+void DeleteEntry (table *entry)
+#endif
+{
+  entry -> type = TBL_DELETED;
+
+  if (firstunused > entry - scantable)
+    firstunused = entry - scantable;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vector.c	Tue Feb 24 18:53:52 2015 +0200
@@ -0,0 +1,126 @@
+/*\
+ *  dxa v0.1.1 -- symbolic 65xx disassembler
+ *
+ *  Copyright (C) 1993, 1994 Marko M\"akel\"a
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Contacting the author:
+ *
+ *   Via Internet E-mail:
+ *      <Marko.Makela@FTP.FUNET.FI>
+ *
+ *   Via Snail Mail:
+ *      Marko M\"akel\"a
+ *      Sillitie 10 A
+ *      FIN-01480 VANTAA
+ *      Finland
+\*/
+
+#define _VECTOR_C_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "proto.h"
+#include "options.h"
+
+unsigned WordCount = 0;
+words *WordTable = NULL;
+
+void AddWordEntry PROTO((ADDR_T start, ADDR_T end));
+
+#ifndef __STDC__
+void
+AddWordEntry (start, end)
+     ADDR_T start;
+     ADDR_T end;
+#else
+void AddWordEntry (ADDR_T start, ADDR_T end)
+#endif
+{
+  words *entry;
+
+  entry = WordCount ?
+    realloc (WordTable, (WordCount + 1) * sizeof *entry) :
+    malloc (sizeof *entry);
+
+  if (!entry) return;
+
+  WordTable = entry;
+  entry += WordCount++;
+  entry->start = start;
+  entry->end = end;
+}
+
+#ifndef __STDC__
+ADDR_T
+WordTableEnd (start)
+     ADDR_T start;
+#else
+ADDR_T WordTableEnd (ADDR_T start)
+#endif
+{
+  words *entry;
+
+  if (!((entry = &WordTable[WordCount])))
+    return start;
+
+  while (entry-- > WordTable)
+    if (entry->start == start)
+      return entry->end;
+
+  return start;
+}
+
+#ifndef __STDC__
+void
+SearchVectors ()
+#else
+void SearchVectors (void)
+#endif
+{
+  ADDR_T start, end, address;
+
+  if ((Options & M_ADR_TABLES) == O_TBL_IGNORE) return;
+
+  if (fVerbose)
+    fprintf (stderr, "%s: Searching for address tables.\n", prog);
+
+  for (start = StartAddress; start != EndAddress; start++) {
+    if (GetMemType (start) != MEM_DATA || !IsLowByte (Memory[start]))
+      continue;
+
+    for (end = start; (end | 1) != (1 | EndAddress); end += 2) {
+      if (GetMemType (end) != MEM_DATA || GetMemType (end + 1) != MEM_DATA)
+        break;
+
+      address = Memory[end] | (Memory[(ADDR_T)(end + 1)] << 8);
+
+      if (!IsLabeled (address))
+        break;
+
+      if ((Options & M_ADR_TABLES) == O_TBL_NOEXT &&
+          (ADDR_T)(address - StartAddress) >=
+          (ADDR_T)(EndAddress - StartAddress))
+        break;
+    }
+
+    if ((ADDR_T)(end - start) > 2) {
+      AddWordEntry (start, end);
+      if (EndAddress == (start = end)) break;
+    }
+  }
+}