1 //============================================================================ 2 // 3 // SSSS tt lll lll 4 // SS SS tt ll ll 5 // SS tttttt eeee ll ll aaaa 6 // SSSS tt ee ee ll ll aa 7 // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" 8 // SS SS tt ee ll ll aa aa 9 // SSSS ttt eeeee llll llll aaaaa 10 // 11 // Copyright (c) 1995-2014 by Bradford W. Mott, Stephen Anthony 12 // and the Stella Team 13 // 14 // See the file "License.txt" for information on usage and redistribution of 15 // this file, and for a DISCLAIMER OF ALL WARRANTIES. 16 // 17 // $Id: DiStella.hxx 2838 2014-01-17 23:34:03Z stephena $ 18 //============================================================================ 19 20 #ifndef DISTELLA_HXX 21 #define DISTELLA_HXX 22 23 #include <queue> 24 #include <sstream> 25 26 #include "Array.hxx" 27 #include "Base.hxx" 28 #include "CartDebug.hxx" 29 #include "bspf.hxx" 30 31 /** 32 This class is a wrapper around the Distella code. Much of the code remains 33 exactly the same, except that generated data is now redirected to a 34 DisassemblyList structure rather than being printed. 35 36 All 7800-related stuff has been removed, as well as all commandline options. 37 Over time, some of the configurability of Distella may be added again. 38 39 @author Stephen Anthony 40 */ 41 class DiStella 42 { 43 public: 44 // A list of options that can be applied to the disassembly 45 // This will eventually grow to include all options supported by 46 // standalone Distella 47 typedef struct { 48 Common::Base::Format gfx_format; 49 bool resolve_code; // Attempt to detect code vs. data sections 50 bool show_addresses; // Show PC addresses (always off for external output) 51 bool aflag; // Turns 'A' off in accumulator instructions (-a in Distella) 52 bool fflag; // Forces correct address length (-f in Distella) 53 bool rflag; // Relocate calls out of address range (-r in Distella) 54 int bwidth; // Number of bytes to use per line (with .byte xxx) 55 } Settings; 56 static Settings settings; // Default settings 57 58 public: 59 /** 60 Disassemble the current state of the System from the given start address. 61 62 @param dbg The CartDebug instance containing all label information 63 @param list The results of the disassembly are placed here 64 @param info Various info about the current bank 65 @param settings The various distella flags/options to use 66 @param labels Array storing label info determined by Distella 67 @param directives Array storing directive info determined by Distella 68 @param reserved The TIA/RIOT addresses referenced in the disassembled code 69 */ 70 DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list, 71 CartDebug::BankInfo& info, const DiStella::Settings& settings, 72 uInt8* labels, uInt8* directives, 73 CartDebug::ReservedEquates& reserved); 74 75 ~DiStella(); 76 77 private: 78 // Indicate that a new line of disassembly has been completed 79 // In the original Distella code, this indicated a new line to be printed 80 // Here, we add a new entry to the DisassemblyList 81 void addEntry(CartDebug::DisasmType type); 82 83 // Process directives given in the list 84 // Directives are basically the contents of a distella configuration file 85 void processDirectives(const CartDebug::DirectiveList& directives); 86 87 // These functions are part of the original Distella code 88 void disasm(uInt32 distart, int pass); 89 bool check_range(uInt16 start, uInt16 end) const; 90 int mark(uInt32 address, uInt8 mask, bool directive = false); 91 bool check_bit(uInt16 address, uInt8 mask) const; 92 93 // Convenience methods to generate appropriate labels labelA12High(stringstream & buf,uInt8 op,uInt16 addr,int labfound)94 inline void labelA12High(stringstream& buf, uInt8 op, uInt16 addr, int labfound) 95 { 96 if(!myDbg.getLabel(buf, addr, true)) 97 buf << "L" << Common::Base::HEX4 << addr; 98 } labelA12Low(stringstream & buf,uInt8 op,uInt16 addr,int labfound)99 inline void labelA12Low(stringstream& buf, uInt8 op, uInt16 addr, int labfound) 100 { 101 myDbg.getLabel(buf, addr, ourLookup[op].rw_mode == READ, 2); 102 if (labfound == 2) 103 { 104 if(ourLookup[op].rw_mode == READ) 105 myReserved.TIARead[addr & 0x0F] = true; 106 else 107 myReserved.TIAWrite[addr & 0x3F] = true; 108 } 109 else if (labfound == 3) 110 myReserved.IOReadWrite[(addr & 0xFF) - 0x80] = true; 111 else if (labfound == 5) 112 myReserved.ZPRAM[(addr & 0xFF) - 0x80] = true; 113 } 114 115 private: 116 const CartDebug& myDbg; 117 CartDebug::DisassemblyList& myList; 118 const Settings& mySettings; 119 CartDebug::ReservedEquates& myReserved; 120 stringstream myDisasmBuf; 121 queue<uInt16> myAddressQueue; 122 uInt16 myOffset, myPC, myPCBeg, myPCEnd; 123 124 struct resource { 125 uInt16 start; 126 uInt16 end; 127 uInt16 length; 128 } myAppData; 129 130 /* Stores info on how each address is marked, both in the general 131 case as well as when manual directives are enabled (in which case 132 the directives take priority 133 The address mark type is defined in CartDebug.hxx 134 */ 135 uInt8 *myLabels, *myDirectives; 136 137 /** 138 Enumeration of the 6502 addressing modes 139 */ 140 enum AddressingMode 141 { 142 IMPLIED, ACCUMULATOR, IMMEDIATE, 143 ZERO_PAGE, ZERO_PAGE_X, ZERO_PAGE_Y, 144 ABSOLUTE, ABSOLUTE_X, ABSOLUTE_Y, 145 ABS_INDIRECT, INDIRECT_X, INDIRECT_Y, 146 RELATIVE, ASS_CODE 147 }; 148 149 /** 150 Enumeration of the 6502 access modes 151 */ 152 enum AccessMode 153 { 154 M_NONE, M_AC, M_XR, M_YR, M_SP, M_SR, M_PC, M_IMM, M_ZERO, M_ZERX, M_ZERY, 155 M_ABS, M_ABSX, M_ABSY, M_AIND, M_INDX, M_INDY, M_REL, M_FC, M_FD, M_FI, 156 M_FV, M_ADDR, M_, 157 158 M_ACIM, /* Source: AC & IMMED (bus collision) */ 159 M_ANXR, /* Source: AC & XR (bus collision) */ 160 M_AXIM, /* Source: (AC | #EE) & XR & IMMED (bus collision) */ 161 M_ACNC, /* Dest: M_AC and Carry = Negative */ 162 M_ACXR, /* Dest: M_AC, M_XR */ 163 164 M_SABY, /* Source: (ABS_Y & SP) (bus collision) */ 165 M_ACXS, /* Dest: M_AC, M_XR, M_SP */ 166 M_STH0, /* Dest: Store (src & Addr_Hi+1) to (Addr +0x100) */ 167 M_STH1, 168 M_STH2, 169 M_STH3 170 }; 171 172 /** 173 Enumeration of the 6502 read/write mode 174 (if the opcode is reading or writing its operand) 175 */ 176 enum ReadWriteMode 177 { 178 READ, WRITE, NONE 179 }; 180 181 struct Instruction_tag { 182 const char* mnemonic; 183 AddressingMode addr_mode; 184 AccessMode source; 185 ReadWriteMode rw_mode; 186 uInt8 cycles; 187 }; 188 static const Instruction_tag ourLookup[256]; 189 }; 190 191 #endif 192