-
- <?php
-
- /**
- * DISASM6 - A NES-oriented 6502 disassembler which produces asm6 code
- * Created by Frantik 2011-2015
- *
- */
-
- define('VERSION', '1.5');
- define('LEFT_MARGIN', ' ');
-
- $time_start = microtime(true);
-
- $opcodes = array(
- // byte => legal, text, bytes, cycles, addressing mode
- 0x00 => array( 0, 'BRK', 1, 0, 0),
- 0x01 => array( 0, 'ORA', 2, 6, 7),
- 0x02 => array( 1, 'KIL', 1, 0, 0),
- 0x03 => array( 1, 'SLO', 2, 8, 7),
- 0x04 => array( 1, 'NOP', 2, 3, 4),
- 0x05 => array( 0, 'ORA', 2, 3, 4),
- 0x06 => array( 0, 'ASL', 2, 5, 4),
- 0x07 => array( 1, 'SLO', 2, 5, 4),
- 0x08 => array( 0, 'PHP', 1, 3, 0),
- 0x09 => array( 0, 'ORA', 2, 2, 0),
- 0x0A => array( 0, 'ASL', 1, 2, 0),
- 0x0B => array( 1, 'ANC', 2, 2, 0),
- 0x0C => array( 1, 'NOP', 3, 4, 1),
- 0x0D => array( 0, 'ORA', 3, 4, 1),
- 0x0E => array( 0, 'ASL', 3, 6, 1),
- 0x0F => array( 1, 'SLO', 3, 6, 1),
- 0x10 => array( 0, 'BPL', 2, 3, 0),
- 0x11 => array( 0, 'ORA', 2, 5, 8),
- 0x12 => array( 1, 'KIL', 1, 0, 0),
- 0x13 => array( 1, 'SLO', 2, 8, 8),
- 0x14 => array( 1, 'NOP', 2, 4, 5),
- 0x15 => array( 0, 'ORA', 2, 4, 5),
- 0x16 => array( 0, 'ASL', 2, 6, 5),
- 0x17 => array( 1, 'SLO', 2, 6, 5),
- 0x18 => array( 0, 'CLC', 1, 2, 0),
- 0x19 => array( 0, 'ORA', 3, 4, 3),
- 0x1A => array( 1, 'NOP', 1, 2, 0),
- 0x1B => array( 1, 'SLO', 3, 7, 3),
- 0x1C => array( 1, 'NOP', 3, 4, 2),
- 0x1D => array( 0, 'ORA', 3, 4, 2),
- 0x1E => array( 0, 'ASL', 3, 7, 2),
- 0x1F => array( 1, 'SLO', 3, 7, 2),
- 0x20 => array( 0, 'JSR', 3, 6, 10),
- 0x21 => array( 0, 'AND', 2, 6, 7),
- 0x22 => array( 1, 'KIL', 1, 0, 0),
- 0x23 => array( 1, 'RLA', 2, 8, 7),
- 0x24 => array( 0, 'BIT', 2, 3, 4),
- 0x25 => array( 0, 'AND', 2, 3, 4),
- 0x26 => array( 0, 'ROL', 2, 5, 4),
- 0x27 => array( 1, 'RLA', 2, 5, 4),
- 0x28 => array( 0, 'PLP', 1, 4, 0),
- 0x29 => array( 0, 'AND', 2, 2, 0),
- 0x2A => array( 0, 'ROL', 1, 2, 0),
- 0x2B => array( 1, 'ANC', 2, 2, 0),
- 0x2C => array( 0, 'BIT', 3, 4, 1),
- 0x2D => array( 0, 'AND', 3, 4, 1),
- 0x2E => array( 0, 'ROL', 3, 6, 1),
- 0x2F => array( 1, 'RLA', 3, 6, 1),
- 0x30 => array( 0, 'BMI', 2, 2, 0),
- 0x31 => array( 0, 'AND', 2, 5, 8),
- 0x32 => array( 1, 'KIL', 1, 0, 0),
- 0x33 => array( 1, 'RLA', 2, 8, 8),
- 0x34 => array( 1, 'NOP', 2, 4, 5),
- 0x35 => array( 0, 'AND', 2, 4, 5),
- 0x36 => array( 0, 'ROL', 2, 6, 5),
- 0x37 => array( 1, 'RLA', 2, 6, 5),
- 0x38 => array( 0, 'SEC', 1, 2, 0),
- 0x39 => array( 0, 'AND', 3, 4, 3),
- 0x3A => array( 1, 'NOP', 1, 2, 0),
- 0x3B => array( 1, 'RLA', 3, 7, 3),
- 0x3C => array( 1, 'NOP', 3, 4, 2),
- 0x3D => array( 0, 'AND', 3, 4, 2),
- 0x3E => array( 0, 'ROL', 3, 7, 2),
- 0x3F => array( 1, 'RLA', 3, 7, 2),
- 0x40 => array( 0, 'RTI', 1, 6, 0),
- 0x41 => array( 0, 'EOR', 2, 6, 7),
- 0x42 => array( 1, 'KIL', 1, 0, 0),
- 0x43 => array( 1, 'SRE', 2, 8, 7),
- 0x44 => array( 1, 'NOP', 2, 3, 4),
- 0x45 => array( 0, 'EOR', 2, 3, 4),
- 0x46 => array( 0, 'LSR', 2, 5, 4),
- 0x47 => array( 1, 'SRE', 2, 5, 4),
- 0x48 => array( 0, 'PHA', 1, 3, 0),
- 0x49 => array( 0, 'EOR', 2, 2, 0),
- 0x4A => array( 0, 'LSR', 1, 2, 0),
- 0x4B => array( 1, 'ALR', 2, 2, 0),
- 0x4C => array( 0, 'JMP', 3, 3, 10),
- 0x4D => array( 0, 'EOR', 3, 4, 1),
- 0x4E => array( 0, 'LSR', 3, 6, 1),
- 0x4F => array( 1, 'SRE', 3, 6, 1),
- 0x50 => array( 0, 'BVC', 2, 3, 0),
- 0x51 => array( 0, 'EOR', 2, 5, 8),
- 0x52 => array( 1, 'KIL', 1, 0, 0),
- 0x53 => array( 1, 'SRE', 2, 8, 8),
- 0x54 => array( 1, 'NOP', 2, 4, 5),
- 0x55 => array( 0, 'EOR', 2, 4, 5),
- 0x56 => array( 0, 'LSR', 2, 6, 5),
- 0x57 => array( 1, 'SRE', 2, 6, 5),
- 0x58 => array( 0, 'CLI', 1, 2, 0),
- 0x59 => array( 0, 'EOR', 3, 4, 3),
- 0x5A => array( 1, 'NOP', 1, 2, 0),
- 0x5B => array( 1, 'SRE', 3, 7, 3),
- 0x5C => array( 1, 'NOP', 3, 4, 2),
- 0x5D => array( 0, 'EOR', 3, 4, 2),
- 0x5E => array( 0, 'LSR', 3, 7, 2),
- 0x5F => array( 1, 'SRE', 3, 7, 2),
- 0x60 => array( 0, 'RTS', 1, 6, 0),
- 0x61 => array( 0, 'ADC', 2, 6, 7),
- 0x62 => array( 1, 'KIL', 1, 0, 0),
- 0x63 => array( 1, 'RRA', 2, 8, 7),
- 0x64 => array( 1, 'NOP', 2, 3, 4),
- 0x65 => array( 0, 'ADC', 2, 3, 4),
- 0x66 => array( 0, 'ROR', 2, 5, 4),
- 0x67 => array( 1, 'RRA', 2, 5, 4),
- 0x68 => array( 0, 'PLA', 1, 4, 0),
- 0x69 => array( 0, 'ADC', 2, 2, 0),
- 0x6A => array( 0, 'ROR', 1, 2, 0),
- 0x6B => array( 1, 'ARR', 2, 2, 0),
- 0x6C => array( 0, 'JMP', 3, 5, 9),
- 0x6D => array( 0, 'ADC', 3, 4, 1),
- 0x6E => array( 0, 'ROR', 3, 6, 1),
- 0x6F => array( 1, 'RRA', 3, 6, 1),
- 0x70 => array( 0, 'BVS', 2, 2, 0),
- 0x71 => array( 0, 'ADC', 2, 5, 8),
- 0x72 => array( 1, 'KIL', 1, 0, 0),
- 0x73 => array( 1, 'RRA', 2, 8, 8),
- 0x74 => array( 1, 'NOP', 2, 4, 5),
- 0x75 => array( 0, 'ADC', 2, 4, 5),
- 0x76 => array( 0, 'ROR', 2, 6, 5),
- 0x77 => array( 1, 'RRA', 2, 6, 5),
- 0x78 => array( 0, 'SEI', 1, 2, 0),
- 0x79 => array( 0, 'ADC', 3, 4, 3),
- 0x7A => array( 1, 'NOP', 1, 2, 0),
- 0x7B => array( 1, 'RRA', 3, 7, 3),
- 0x7C => array( 1, 'NOP', 3, 4, 2),
- 0x7D => array( 0, 'ADC', 3, 4, 2),
- 0x7E => array( 0, 'ROR', 3, 7, 2),
- 0x7F => array( 1, 'RRA', 3, 7, 2),
- 0x80 => array( 1, 'NOP', 2, 2, 0),
- 0x81 => array( 0, 'STA', 2, 6, 7),
- 0x82 => array( 1, 'NOP', 2, 2, 0),
- 0x83 => array( 1, 'SAX', 2, 6, 7),
- 0x84 => array( 0, 'STY', 2, 3, 4),
- 0x85 => array( 0, 'STA', 2, 3, 4),
- 0x86 => array( 0, 'STX', 2, 3, 4),
- 0x87 => array( 1, 'SAX', 2, 3, 4),
- 0x88 => array( 0, 'DEY', 1, 2, 0),
- 0x89 => array( 1, 'NOP', 2, 2, 0),
- 0x8A => array( 0, 'TXA', 1, 2, 0),
- 0x8B => array( 1, 'XAA', 2, 2, 0),
- 0x8C => array( 0, 'STY', 3, 4, 1),
- 0x8D => array( 0, 'STA', 3, 4, 1),
- 0x8E => array( 0, 'STX', 3, 4, 1),
- 0x8F => array( 1, 'SAX', 3, 4, 1),
- 0x90 => array( 0, 'BCC', 2, 3, 0),
- 0x91 => array( 0, 'STA', 2, 6, 8),
- 0x92 => array( 1, 'KIL', 1, 0, 0),
- 0x93 => array( 1, 'AHX', 2, 6, 8),
- 0x94 => array( 0, 'STY', 2, 4, 5),
- 0x95 => array( 0, 'STA', 2, 4, 5),
- 0x96 => array( 0, 'STX', 2, 4, 6),
- 0x97 => array( 1, 'SAX', 2, 4, 6),
- 0x98 => array( 0, 'TYA', 1, 2, 0),
- 0x99 => array( 0, 'STA', 3, 5, 3),
- 0x9A => array( 0, 'TXS', 1, 2, 0),
- 0x9B => array( 1, 'TAS', 1, 5, 0),
- 0x9C => array( 1, 'SHY', 3, 5, 2),
- 0x9D => array( 0, 'STA', 3, 5, 2),
- 0x9E => array( 1, 'SHX', 3, 5, 3),
- 0x9F => array( 1, 'AHX', 3, 5, 3),
- 0xA0 => array( 0, 'LDY', 2, 2, 0),
- 0xA1 => array( 0, 'LDA', 2, 6, 7),
- 0xA2 => array( 0, 'LDX', 2, 2, 0),
- 0xA3 => array( 1, 'LAX', 2, 6, 7),
- 0xA4 => array( 0, 'LDY', 2, 3, 4),
- 0xA5 => array( 0, 'LDA', 2, 3, 4),
- 0xA6 => array( 0, 'LDX', 2, 3, 4),
- 0xA7 => array( 1, 'LAX', 2, 3, 4),
- 0xA8 => array( 0, 'TAY', 1, 2, 0),
- 0xA9 => array( 0, 'LDA', 2, 2, 0),
- 0xAA => array( 0, 'TAX', 1, 2, 0),
- 0xAB => array( 1, 'LAX', 2, 2, 0),
- 0xAC => array( 0, 'LDY', 3, 4, 1),
- 0xAD => array( 0, 'LDA', 3, 4, 1),
- 0xAE => array( 0, 'LDX', 3, 4, 1),
- 0xAF => array( 1, 'LAX', 3, 4, 1),
- 0xB0 => array( 0, 'BCS', 2, 2, 0),
- 0xB1 => array( 0, 'LDA', 2, 5, 8),
- 0xB2 => array( 1, 'KIL', 1, 0, 0),
- 0xB3 => array( 1, 'LAX', 2, 5, 8),
- 0xB4 => array( 0, 'LDY', 2, 4, 5),
- 0xB5 => array( 0, 'LDA', 2, 4, 5),
- 0xB6 => array( 0, 'LDX', 2, 4, 6),
- 0xB7 => array( 1, 'LAX', 2, 4, 6),
- 0xB8 => array( 0, 'CLV', 1, 2, 0),
- 0xB9 => array( 0, 'LDA', 3, 4, 3),
- 0xBA => array( 0, 'TSX', 1, 2, 0),
- 0xBB => array( 1, 'LAS', 3, 4, 3),
- 0xBC => array( 0, 'LDY', 3, 4, 2),
- 0xBD => array( 0, 'LDA', 3, 4, 2),
- 0xBE => array( 0, 'LDX', 3, 4, 3),
- 0xBF => array( 1, 'LAX', 3, 4, 3),
- 0xC0 => array( 0, 'CPY', 2, 2, 0),
- 0xC1 => array( 0, 'CMP', 2, 6, 7),
- 0xC2 => array( 1, 'NOP', 2, 2, 0),
- 0xC3 => array( 1, 'DCP', 2, 8, 7),
- 0xC4 => array( 0, 'CPY', 2, 3, 4),
- 0xC5 => array( 0, 'CMP', 2, 3, 4),
- 0xC6 => array( 0, 'DEC', 2, 5, 4),
- 0xC7 => array( 1, 'DCP', 2, 5, 4),
- 0xC8 => array( 0, 'INY', 1, 2, 0),
- 0xC9 => array( 0, 'CMP', 2, 2, 0),
- 0xCA => array( 0, 'DEX', 1, 2, 0),
- 0xCB => array( 1, 'AXS', 2, 2, 0),
- 0xCC => array( 0, 'CPY', 3, 4, 1),
- 0xCD => array( 0, 'CMP', 3, 4, 1),
- 0xCE => array( 0, 'DEC', 3, 6, 1),
- 0xCF => array( 1, 'DCP', 3, 6, 1),
- 0xD0 => array( 0, 'BNE', 2, 3, 0),
- 0xD1 => array( 0, 'CMP', 2, 5, 8),
- 0xD2 => array( 1, 'KIL', 1, 0, 0),
- 0xD3 => array( 1, 'DCP', 2, 8, 8),
- 0xD4 => array( 1, 'NOP', 2, 4, 5),
- 0xD5 => array( 0, 'CMP', 2, 4, 5),
- 0xD6 => array( 0, 'DEC', 2, 6, 5),
- 0xD7 => array( 1, 'DCP', 2, 6, 5),
- 0xD8 => array( 0, 'CLD', 1, 2, 0),
- 0xD9 => array( 0, 'CMP', 3, 4, 3),
- 0xDA => array( 1, 'NOP', 1, 2, 0),
- 0xDB => array( 1, 'DCP', 3, 7, 3),
- 0xDC => array( 1, 'NOP', 3, 4, 2),
- 0xDD => array( 0, 'CMP', 3, 4, 2),
- 0xDE => array( 0, 'DEC', 3, 7, 2),
- 0xDF => array( 1, 'DCP', 3, 7, 2),
- 0xE0 => array( 0, 'CPX', 2, 2, 0),
- 0xE1 => array( 0, 'SBC', 2, 6, 7),
- 0xE2 => array( 1, 'NOP', 2, 2, 0),
- 0xE3 => array( 1, 'ISC', 2, 8, 7),
- 0xE4 => array( 0, 'CPX', 2, 3, 4),
- 0xE5 => array( 0, 'SBC', 2, 3, 4),
- 0xE6 => array( 0, 'INC', 2, 5, 4),
- 0xE7 => array( 1, 'ISC', 2, 5, 4),
- 0xE8 => array( 0, 'INX', 1, 2, 0),
- 0xE9 => array( 0, 'SBC', 2, 2, 0),
- 0xEA => array( 0, 'NOP', 1, 2, 0),
- 0xEB => array( 1, 'SBC', 2, 2, 0),
- 0xEC => array( 0, 'CPX', 3, 4, 1),
- 0xED => array( 0, 'SBC', 3, 4, 1),
- 0xEE => array( 0, 'INC', 3, 6, 1),
- 0xEF => array( 1, 'ISC', 3, 6, 1),
- 0xF0 => array( 0, 'BEQ', 2, 2, 0),
- 0xF1 => array( 0, 'SBC', 2, 5, 8),
- 0xF2 => array( 1, 'KIL', 1, 0, 0),
- 0xF3 => array( 1, 'ISC', 2, 8, 8),
- 0xF4 => array( 1, 'NOP', 2, 4, 5),
- 0xF5 => array( 0, 'SBC', 2, 4, 5),
- 0xF6 => array( 0, 'INC', 2, 6, 5),
- 0xF7 => array( 1, 'ISC', 2, 6, 5),
- 0xF8 => array( 0, 'SED', 1, 2, 0),
- 0xF9 => array( 0, 'SBC', 3, 4, 3),
- 0xFA => array( 1, 'NOP', 1, 2, 0),
- 0xFB => array( 1, 'ISC', 3, 7, 3),
- 0xFC => array( 1, 'NOP', 3, 4, 2),
- 0xFD => array( 0, 'SBC', 3, 4, 2),
- 0xFE => array( 0, 'INC', 3, 7, 2),
- 0xFF => array( 1, 'ISC', 3, 7, 2),
- );
-
-
- $registers = array(
- '2000' => 'PPUCTRL',
- '2001' => 'PPUMASK',
- '2002' => 'PPUSTATUS',
- '2003' => 'OAMADDR',
- '2004' => 'OAMDATA',
- '2005' => 'PPUSCROLL',
- '2006' => 'PPUADDR',
- '2007' => 'PPUDATA',
-
- '4000' => 'SQ1_VOL',
- '4001' => 'SQ1_SWEEP',
- '4002' => 'SQ1_LO',
- '4003' => 'SQ1_HI',
- '4004' => 'SQ2_VOL',
- '4005' => 'SQ2_SWEEP',
- '4006' => 'SQ2_LO',
- '4007' => 'SQ2_HI',
- '4008' => 'TRI_LINEAR',
- '400A' => 'TRI_LO',
- '400B' => 'TRI_HI',
- '400C' => 'NOISE_VOL',
- '400E' => 'NOISE_LO',
- '400F' => 'NOISE_HI',
- '4010' => 'DMC_FREQ',
- '4011' => 'DMC_RAW',
- '4012' => 'DMC_START',
- '4013' => 'DMC_LEN',
- '4014' => 'OAM_DMA',
- '4015' => 'SND_CHN',
- '4016' => 'JOY1',
- '4017' => 'JOY2',
-
- );
-
- // used for branch opcodes
- function addressOffset($value, $offset)
- {
- $offset = hexdec($offset);
- $offset += 2; // length of brance command
- if ($offset > 0x80)
- {
- $offset = $offset - 0x100;
- }
- else
- {
- //$offset += 2;
- }
- return str_pad(dechex($value + $offset), 4, '0', STR_PAD_LEFT);
- }
-
- function isValidLabel($addr)
- {
- global $origin;
-
- $newaddr = hexdec($addr);
-
- return ($newaddr >= $origin && $newaddr < 0xFFFA);
- }
-
- function addValidLabel($addr, &$labels)
- {
- if (isValidLabel($addr) && !isset($labels[$addr]))
- {
- $labels[$addr] = true;
- return true;
- }
-
- return false;
- }
-
-
- function addVector($vector, $str, &$labels)
- {
- if (isset($labels[$vector]))
- {
- if ($labels[$vector] === true)
- {
- $labels[$vector] = $str;
- }
- elseif (is_array($labels[$vector]))
- {
- if( !in_array($str, $labels[$vector]))
- {
- $labels[$vector][] = $str;
- }
- }
- elseif ($labels[$vector] !== $str)
- {
- $labels[$vector] = array($labels[$vector], $str);
- }
- }
- else
- {
- $labels[$vector] = $str;
- }
- }
-
- function wordStr($str)
- {
- return dechex_pad(ord($str[1])) . dechex_pad(ord($str[0]));
- }
-
- // make sure hex values have leading zeros
- function dechex_pad($dec , $len = 2)
- {
-
- if ($dec > 0xFF)
- {
- $len = 4;
- }
- elseif ($dec > 0xFFFF)
- {
- $len = 6;
- }
-
- return str_pad(dechex($dec), $len, '0', STR_PAD_LEFT);
- }
-
- // make sure binary values have leading zeros
- function decbin_pad($dec , $len = 8)
- {
-
- if ($dec > 0xFF)
- {
- $len = 16;
- }
- elseif ($dec > 0xFFFF)
- {
- $len = 32;
- }
-
- return str_pad(decbin($dec), $len, '0', STR_PAD_LEFT);
- }
-
- function commentLine($len = 80)
- {
- return ";" . str_repeat('-', $len - 1) . "\n";
- }
-
- function commentHeader($text, $initialNL = true, $initialLine = true)
- {
- $ret = ($initialNL ? "\n" : '') . ($initialLine ? commentLine() : '');
- $ret .= "; $text";
- $ret .= "\n" . commentLine();
-
- return $ret;
- }
-
- function strToHex($str, $fancy = false)
- {
- $len = strlen($str);
-
- $ret = '';
-
- for($i = 0; $i < $len; $i++)
- {
- $ret .= ($fancy ? '$' : '') . dechex_pad(ord($str[$i]));
-
- if ($i < $len - 1)
- { $ret .= ($fancy ? ',' : '') . " ";
- }
- }
-
- return $ret;
- }
-
- function getHeaderInfo($file)
- {
- $oldloc = ftell($file);
-
- $head = fread($file, 0x4);
-
- if ($head == "NES" . chr(0x1A))
- {
- $info = new stdClass;
-
- $info->head = $head;
- $info->prg = ord(fread($file, 1));
- $info->chr = ord(fread($file, 1));
- $info->ctrl_1 = ord(fread($file, 1));
- $info->ctrl_2 = ord(fread($file, 1));
- $info->tail = fread($file, 8);
-
- $info->mirroring = $info->ctrl_1 & bindec('00000001');
- $info->sram = ($info->ctrl_1 & bindec('0000010')) >> 1;
- $info->trainer = ($info->ctrl_1 & bindec('00000100')) >> 2;
- $info->fourscreen = ($info->ctrl_1 & bindec('00001000')) >> 3;
-
- $info->romtype = $info->ctrl_2 & bindec('00000011');
-
- $info->mapper = (($info->ctrl_1 & bindec('11110000')) >> 4)
- + $info->ctrl_2 & bindec('00001111');
-
- return $info;
-
- }
- else
- {
- fseek($file, $oldloc);
- return false;
- }
- }
-
- function processHeaderInfo($info)
- {
- global $labelLen;
-
- $pad = 30 + $labelLen;
- $ret = '';
- if (is_object($info))
- {
- //$ret .= commentLine();
- $ret .= commentHeader("iNES Header");
- $ret .= str_pad(LEFT_MARGIN . '.db "NES", $1A', $pad) . " ; Header\n";
- $ret .= str_pad(LEFT_MARGIN . ".db $info->prg", $pad) . " ; $info->prg x 16k PRG banks\n";
- $ret .= str_pad(LEFT_MARGIN . ".db $info->chr", $pad) . " ; $info->chr x 8k CHR banks\n";
- $ret .= str_pad(LEFT_MARGIN . ".db %" . decbin_pad($info->ctrl_1), $pad) . " ; Mirroring: " . ($info->mirroring ? 'Vertical' : 'Horizontal') . "\n";
- $ret .= str_repeat(" ", $pad) . " ; SRAM: " . ($info->sram ? 'Enabled' : 'Not used') . "\n";
- $ret .= str_repeat(" ", $pad) . " ; 512k Trainer: " . ($info->trainer ? 'Enabled' : 'Not used') . "\n";
- $ret .= str_repeat(" ", $pad) . " ; 4 Screen VRAM: " . ($info->fourscreen ? 'Enabled' : 'Not used') . "\n";
- $ret .= str_repeat(" ", $pad) . " ; Mapper: " . $info->mapper . "\n";
-
- switch($info->romtype)
- {
- case 0:
- $romtype = 'NES';
- break;
- case 1:
- $romtype = 'VS Unisystem';
- break;
- case 2:
- $romtype = 'Playchoice 10';
- break;
- }
- $ret .= str_pad(LEFT_MARGIN . ".db %" . decbin_pad($info->ctrl_2), $pad) . " ; RomType: " . $romtype . "\n";
-
- $ret .= str_pad(LEFT_MARGIN . ".hex " . strToHex(substr($info->tail,0,4)), $pad) . " ; iNES Tail \n";
- $ret .= str_pad(LEFT_MARGIN . ".hex " . strToHex(substr($info->tail,4)), $pad) . " \n";
-
- return $ret;
- }
-
- return false;
- }
-
- function toLittleEndianStr($str)
- {
- return $str[2] . $str[3] . " " . $str[0] . $str[1];
- }
-
- function processVectors($nmi, $reset, $break)
- {
- global $labelLen;
-
- $marginLen = strlen(LEFT_MARGIN);
- $pad = 30 + $marginLen;
-
- $ret = commentHeader('Vector Table');
- $line1 = str_pad("vectors:", $marginLen);
- $line1 .= ".dw nmi";
- $ret = $ret . str_pad($line1, $pad) . ' ; $fffa: ' . toLittleEndianStr($nmi) . " Vector table\n";
- $ret .= str_pad(LEFT_MARGIN . ".dw reset", $pad) . ' ; $fffc: ' . toLittleEndianStr($reset) . " Vector table\n";
- $ret .= str_pad(LEFT_MARGIN . ".dw irq", $pad) . ' ; $fffe: ' . toLittleEndianStr($break) . " Vector table\n";
-
- return $ret;
- }
-
- function baseToDec($str)
- {
- switch ($str{0})
- {
- case '0':
- if ($str[1] !== 'x')
- { break;
- }
- else
- {
- return hexdec(substr($str,2));
- }
- break;
-
- case '$':
- return hexdec(substr($str,1));
- break;
-
- case '$':
- return bindec(substr($str,1));
- break;
- }
- return $str;
- }
-
- function readLabels($filename)
- {
-
- $arr = readLabelText(file_get_contents($filename));
-
- return $arr;
-
-
- }
- function readLabelText($str)
- {
- $arr = array();
- $len = 0;
- $str = preg_replace('%;.*$%m', '', $str);
-
- if (preg_match_all('%^\s*([a-zA-Z0-9_\-\+\@]*)\s*\=\s*([\$\%]*)([a-fA-F0-9]*)%m', $str, $matches))
- {
- foreach($matches[0] as $n => $v)
- { $matches[1][$n] = trim($matches[1][$n]);
-
- $thislen = strlen($matches[1][$n]);
-
- if ($thislen > $len)
- {
- $len = $thislen;
- }
-
- if (strlen($matches[1][$n]) > 0)
- {
- if ($matches[2][$n] == '')
- { $matches[3][$n] = dechex_pad($matches[3][$n]);
- }
-
- if ($matches[2][$n] == '%')
- {
- $matches[3][$n] = dechex_pad(bindec($matches[3][$n]));
- }
-
- $arr[strtolower($matches[3][$n])] = $matches[1][$n];
- }
- }
- }
-
- $arr['maxLength'] = $len;
-
- return $arr;
- }
-
- function outputLabels($arr, $text)
- {
- global $origin;
-
- $ret = commentHeader($text);
-
- foreach ($arr as $n => $v)
- {
- if ($n == 'maxLength')
- {
- continue;
- }
-
- if (hexdec($n) < $origin)
- {
- $ret .= str_pad($v , 20) . ' = $' . $n . "\n";
- }
- }
-
- return $ret;
-
- }
-
- function outputHelp($text = false)
- {
- global $argv;
- $dasm = pathinfo($argv[0], PATHINFO_BASENAME);
-
- echo <<<ENDOFSTRING
- Usage:
-
- disasm6 <file> [-t <file>] [-o #] [-l <file>] [-cdl <file>] [-cdlo #] [-d] [-i]
- [-h] [-c] [-p #] [-r] [-lc] [-uc] [-fs #] [-cs #] [-fe #] [-ce <#>]
- [-len #] [-iw] [-m2]
-
- <file> The file to disassemble
- t target <file> Target output filename (default is input filename.asm)
- o origin # Set the program origin.
- (default: 0x8000 for 32k roms, 0xC000 for 16k roms)
- l labels <file> Load user defined labels from file
- cdl cdl <file> Use a code/data log generated by FCEUX
- cdlo cdloffset # Set the offset of the cdl file
- d nodetect Disable 16kb prg size detection
- i ignoreheader Do not look for iNES header
- h noheader Do not include iNES header (if found) in disassembly
- c chr Export CHR-ROM as file and include in disassembly
- p passes # Maximum number of passes (default: 9)
- r registers Use default NES registers
- lc lowercase Use lowercase mnemonics [default]
- uc uppercase Use uppercase mnemonics
- fs filestart Start reading at a specific file location
- cs codestart Start reading at a specific code location
- fe fileend Stop reading at a specific file location
- ce codeend Stop reading at a specific code location
- len length Number of bytes to read
- iw ignorewrites Ignore writes to \$8000 - \$FFFF
- m2 mapper2 Enable mapper 2 (UxROM) support
- ENDOFSTRING;
-
- echo "\n" . ($text ? "\nERROR: $text\n" : '');
- exit;
- }
-
- function isCounterLabel($addr, $labels)
- {
- $addr= dechex_pad($addr);
-
- if (isset($labels[$addr]))
- {
- if (preg_match('%^([^\+\-]+)[\+\-][0-9]+%', $labels[$addr]))
- {
- return false;
- }
-
- return true;
- }
- return false;
-
- }
-
- // Program start
-
- $head = "DISASM6 v" . VERSION ." - A NES-oriented 6502 disassembler - Created by Frantik 2015";
- echo "\n$head\n" . str_repeat('-', 79) . "\n";
-
-
-
- if (!isset($argv[1]))
- {
- outputHelp();
- }
- elseif (!file_exists($argv[1]))
- {
- outputHelp("File not found\n");
- }
- else
- {
- $filename = $argv[1];
- }
-
- $origin = 0x8000;
- $showHeader = true;
- $includeChr = false;
- $includeReg = false;
- $originOverride = false;
- $noDetect = false;
- $shortname = pathinfo($filename, PATHINFO_FILENAME);
- $labelFile = false;
- $cdlFilename = false;
- $ignoreHeader = false;
- $fileStart = 0;
- $fileStartOverride = false;
- $fileLength = 0x10000;
- $lengthOverride = false;
- $fileEnd = 0;
- $fileEndOverride = false;
- $codeStart = 0;
- $codeStartOverride = false;
- $codeEnd = 0;
- $codeEndOverride = false;
- $cdlOffset = 0;
- $ignoreWrites = false;
- $useLowerCase = true;
- $usingMapper2 = false;
-
- $lastPass = 9;
-
- $marginLen = strlen(LEFT_MARGIN);
-
- // check command line params
- for ($i = 2; $i < $argc; $i++)
- {
- $nextParam = false;
-
- if (isset($argv[$i + 1]) && substr($argv[$i + 1],0,1) != '-')
- { $nextParam = $argv[$i + 1];
- }
-
- switch (strtolower($argv[$i]))
- {
- case "-o":
- case "-origin":
-
- if (!$nextParam)
- { outputHelp("Must specify a valid origin");
- }
-
- $origin = baseToDec($argv[++$i]);
- $originOverride = true;
- break;
-
- case "-cs":
- case "-codestart":
-
- if (!$nextParam)
- { outputHelp("Must specify a valid code start location ");
- }
-
- $codeStart = baseToDec($argv[++$i]);
- $codeStartOverride = true;
-
- break;
-
- case "-fs":
- case "-filestart":
-
- if (!$nextParam)
- { outputHelp("Must specify a valid file start location ");
- }
-
- $fileStart = baseToDec($argv[++$i]);
- $fileStartOverride = true;
- break;
-
- case '-len':
- case '-length':
- if (!$nextParam)
- { outputHelp("Must specify a valid length to read");
- }
-
- $fileLength = baseToDec($argv[++$i]); // this will be tweaked later
- $lengthOverride = true;
- break;
-
- case "-fe":
- case "-fileend":
-
- if (!$nextParam)
- { outputHelp("Must specify a valid file end location ");
- }
-
- $fileEnd = baseToDec($argv[++$i]);
- $fileEndOverride = true;
- break;
-
- case "-ce":
- case "-codeend":
-
- if (!$nextParam)
- { outputHelp("Must specify a valid code end location ");
- }
-
- $fileLength = baseToDec($argv[++$i]); // will NOT be tweaked since lengthOverride isn't enable
- $codeEndOverride = true;
- break;
-
-
- case "-h":
- case '-noheader';
- $showHeader = false;
- break;
-
- case "-i":
- case '-ignoreheader';
- $ignoreHeader = true;
- break;
-
- case "-c":
- case "-chr":
- $includeChr = true;
- break;
-
- case '-r':
- case '-registers':
- $includeReg = true;
- break;
-
- case '-t':
- case '-target':
- if (!$nextParam)
- { outputHelp("You must specify a target file");
- }
-
- $shortname = pathinfo(preg_replace("%[^a-zA-Z0-9_\-\. ]%", '', $argv[++$i]), PATHINFO_FILENAME);
-
- break;
-
- case '-p':
- case '-passes':
- if (!$nextParam || !is_numeric($nextParam))
- { outputHelp("You must specify a number of passes");
- }
-
- $lastPass = (int)$argv[++$i];
- break;
-
- case '-nodetect':
- case '-d':
- $noDetect = true;
- break;
-
- case '-l':
- case '-labels':
- if (!$nextParam || !file_exists($nextParam))
- { outputHelp("You must specify a valid file");
- }
-
- $labelFile = $argv[++$i];
- break;
-
-
- case '-cdl':
- if (!$nextParam || !file_exists($nextParam))
- { outputHelp("You must specify a valid file");
- }
-
- $cdlFilename = $argv[++$i];
- break;
-
- case '-cdlo':
- case '-cdloffset':
- if (!$nextParam)
- { outputHelp("You must specify a valid offset for the CDL");
- }
-
- $cdlOffset = baseToDec($argv[++$i]);
- break;
-
-
- case '-lc':
- case '-lowercase':
- $useLowerCase = true;
-
- break;
-
- case '-cc':
- case '-uppercase':
- $useLowerCase = false;
-
- break;
-
- case '-iw':
- case '-ignorewrites':
-
- $ignoreWrites = true;
- break;
-
- case '-m2':
- case '-mapper2':
-
- $usingMapper2 = true;
- break;
- }
-
- }
-
-
- if ($fileEndOverride)
- {
- $fileLength = $fileStart + $fileEnd;
- $lengthOverride = true;
- }
-
-
- $file = fopen($filename, 'r');
-
- $pass = 1;
-
- $oldLabels = false;
-
- $initLabels = array(
- 'fffa' => "vectors",
- 'fffc' => true,
- 'fffe' => true,
- );
-
- if ($includeReg)
- {
- $initLabels += $registers;
- }
-
- $labelLen = 0;
- if ($labelFile !== false)
- {
- $fileLabels = readLabels($labelFile);
-
- //$mapperArr = $fileLabels['mapperArr'];
- //unset($fileLabels['mapperArr']);
-
- $labelLen = $fileLabels['maxLength'] - 10;
- $labelLen = $labelLen < 0 ? 0: $labelLen;
- unset ($fileLabels['maxLength']);
-
- $initLabels += $fileLabels;
-
- }
-
- $cdlFile = false;
- if ($cdlFilename !== false)
- {
- $cdlFile = fopen($cdlFilename, 'r');
- $cdlByte = 0;
- }
-
-
- $header = false;
- $theOldLabel = '';
-
- $theText = commentHeader(pathinfo($filename, PATHINFO_BASENAME) . " disasembled by DISASM6 v" . VERSION, false);
- //$invalidCounter = 0;
-
- $prgBank = 0;
- $theLabel = '';
-
-
- // This loop is done x times
- // The first pass we just collect addesses
- // The next passes we look for new addresses
- //
- // The last pass we build the actual output
- while ($pass <= $lastPass)
- {
- if ($pass < 3)
- { $labels = $initLabels;
- }
- $prgLabels = $initLabels;
-
- $counter = $origin;
-
- if ($fileStartOverride && !$codeStartOverride)
- {
- fseek($file, $fileStart);
- }
-
- if (!$ignoreHeader)
- {
- $headerInfo = getHeaderInfo($file);
- }
- else
- {
- $headerInfo = false;
- }
-
- if ($codeStartOverride)
- {
- fseek($file, $fileStart);
- }
-
- if ($headerInfo)
- { $oldPrg = $headerInfo->prg;
- }
- else
- {
-
- }
-
-
- // do this stuff only on the first pass
- if ($pass == 1)
- {
- $oldDidDrawLine = false;
- $oldLabels = $labels;
-
- // check for 16k roms
- if (!$noDetect)
- { $newPrg = false;
- if ($headerInfo && $headerInfo->prg == 2)
- {
- $prg0 = fread($file, 0x4000);
- $prg1 = fread($file, 0x4000);
- fseek($file, $fileStart + 0x10);
-
- if ($prg0 === $prg1 && $headerInfo->mapper == 0)
- { echo "PRG Banks 0 and 1 are identical, 16k PRG suspected, use -d to disable check\n";
- $newPrg = 1;
-
- $origin = $originOverride ? $origin : 0xc000;
-
- if ($cdlFilename !== false)
- {
- $cdlOffset += 0x4000;
- }
- }
- }
- elseif ($headerInfo && $headerInfo->prg == 1)
- {
- $origin = $originOverride ? $origin : 0xc000;
- }
- }
-
-
- echo "Using Origin: 0x" . dechex_pad($origin) . "\n\n";
-
-
- if ($headerInfo !== false)
- {
- echo 'NES Header Found - ' . ($showHeader ? 'included in disassembly' : 'not included') ."\n";
- }
-
- if ($labelFile !== false)
- {
- echo "Using user defined labels\n";
- }
-
- if ($includeReg)
- {
- echo "Using NES registers\n";
- }
-
- if ($cdlFilename !== false)
- {
- echo "Using code/data log\n";
- }
-
- if ($ignoreWrites !== false)
- {
- echo "Writes to PRG will not create labels\n";
- }
-
- if ($usingMapper2 !== false)
- {
- echo "Mapper 2 (UxROM) support enabled\n";
- }
-
-
- if ($fileStartOverride && !$codeStartOverride)
- {
- echo "Starting at file location 0x" . dechex_pad($fileStart) ."\n";
- }
-
- if ($codeStartOverride)
- {
- $fileStart = $codeStart - $origin + ($headerInfo ? 10 : 0);
- $origin = $codeStart;
- $originOverride = true;
-
- $fileStartOverride = true;
- fseek($file, $fileStart);
-
- $cdlOffset += $fileStart - ($headerInfo ? 10 : 0);
-
-
- echo "Starting at code location $" . dechex_pad($fileStart)."\n";
- }
-
- if ($lengthOverride)
- {
- echo "Reading 0x" . dechex_pad($fileLength) . " bytes\n";
-
- $fileLength += $origin - ($headerInfo ? 0x10 : 0);
- }
-
-
- if ($includeChr && $headerInfo !== false)
- {
- //echo "Using CHR-ROM\n";
- }
-
- echo "\n";
- }
-
- if ($cdlFilename !== false)
- {
- fseek($cdlFile, $cdlOffset);
- }
-
- // if 16k rom, update prg info
- if ($newPrg)
- {
- $headerInfo->prg = $newPrg;
- }
-
- // do this stuff only on the lass pass
- if ($pass == $lastPass)
- {
-
- if ($labelFile !== false)
- {
- $theText .= outputLabels($fileLabels, "User Defined Labels");
- }
-
- if ($includeReg)
- {
- $theText .= outputLabels($registers, "Registers");
- }
-
- $header = processHeaderInfo($headerInfo);
-
- if ($header !== false && $showHeader)
- {
- $theText .= $header;
- }
-
- $theText .= commentHeader("Program Origin");
- $theText .= str_pad(LEFT_MARGIN . ".org $" . dechex_pad($counter), 30 + $labelLen) . " ; Set program counter\n";
- $theText .= commentHeader('ROM Start');
-
- }
-
- // read the file
- // each pass of this loop completes one line of output
-
- $counter = $origin;
- echo "Starting pass $pass " . ($pass == $lastPass ? "(final) " : '' ) . "... ";
-
- while (!feof($file) && $counter < $fileLength)
- {
- $add = false;
- $invalidText = "Invalid Opcode";
- $didDrawLine = false;
-
- // handle mapper 2
- if ($usingMapper2
- && $headerInfo
- && $headerInfo->mapper == 2
- && $counter == 0xC000
- && $prgBank < ($headerInfo->prg - 1)
- )
- {
- $counter = 0x8000;
- $prgBank++;
-
- if ($pass == $lastPass)
- { $theText .= commentHeader("PRG Bank $prgBank");
- $theText .= LEFT_MARGIN . ".base 0x8000\n";
- $theText .= commentLine();
- }
- continue;
-
- }
-
- // handle vectors
-
- if ($pass < $lastPass && $counter == 0xFFFA)
- {
- $nmi = wordStr(fread($file, 2));
- $reset = wordStr(fread($file, 2));
- $break = wordStr(fread($file, 2));
-
- addVector($nmi, "nmi", $labels);
- addVector($reset, "reset", $labels);
- addVector($break, "irq", $labels);
-
- $prgLabels[$nmi] = true;
- $prgLabels[$reset] = true;
- $prgLabels[$break] = true;
-
- $counter += 6;
- continue;
- }
- elseif($pass == $lastPass && $counter == 0xFFFA)
- {
- $theText .= processVectors($nmi, $reset, $break);
- fread($file, 6);
-
- $counter += 6;
-
- continue;
- }
-
- //read opcode
- $opcode = ord(fread($file, 1));
-
-
- $isInvalid = $opcodes[$opcode][0];
- $mnemonic = $opcodes[$opcode][1];
- $byteLen = $opcodes[$opcode][2];
- $addressingType = $opcodes[$opcode][4];
-
- $isDataByte = false;
- $dataStr = 'Suspected data';
-
- // check code/data log - if data, don' process as an opcode
- if ($cdlFilename !== false)
- {
- $newCdlByte = ord(fread($cdlFile, 1)) ;
-
-
- // draw line between data and code
- if ($pass == $lastPass
- && !$oldDidDrawLine
- && $counter !== $origin
- && $newCdlByte !== 0
- && (($newCdlByte & bindec('00000001')) != ($cdlByte & bindec('00000001')))
- )
- {
- $theText .= "\n" . commentLine();
-
- $didDrawLine = true;
- }
-
- // check if the CDL byte is known, if known, copy, otherwise do some checks
- if ($newCdlByte !== 0)
- {
- $cdlByte = $newCdlByte;
- }
- // if byte is zero and we're at a program label, assume code
- elseif (isset($oldPrgLabels[dechex_pad($counter)]))
- {
- $cdlByte = bindec('00000001');
- }
- // if byte is zero and we're at a label, but not program, assume data (only on 2nd pass)
- elseif (isset($oldLabels[dechex_pad($counter)]) && $pass > 1)
- {
- $cdlByte = bindec('00000010');
- }
- // else assume program code
-
-
- // data byte
- if ((($cdlByte & bindec('00000010')) >> 1) && !($cdlByte & bindec('00000001')))
- {
-
- $counter_pad = dechex_pad($counter);
-
- if (isCounterLabel($counter, $oldLabels))
- {
- $theOldLabel = $oldLabels[$counter_pad] === true
- ? '__' . $counter_pad
- : $oldLabels[$counter_pad];
-
- //$theOldLabel = preg_replace('%^([^\+\-]+)[\+\-][0-9]+%', '$1', $theOldLabel);
- }
-
- if (substr($theOldLabel, -9) == 'JumpTable')
- {
-
- $byteLen = 2;
- $mnemonic = '.word';
- $addressingType = 11;
- $isInvalid = 0;
- //fseek($file, ftell($file) - 1);
-
-
-
- }
- elseif (substr($theOldLabel, -8) == 'RTSTable')
- {
-
- $byteLen = 2;
- $mnemonic = '.word';
- $addressingType = 12;
- $isInvalid = 0;
-
- }/*
- elseif (substr($theOldLabel, -8) == 'TableLow')
- {
- $byteLen = 1;
- $mnemonic = '.byte';
- $addressingType = 13;
- $isInvalid = 0;
- }
- elseif (substr($theOldLabel, -9) == 'TableHigh')
- {
- $byteLen = 1;
- $mnemonic = '.byte';
- $addressingType = 14;
- $isInvalid = 0;
- } */
- else
- {
- $byteLen = 4;
- //echo substr($theLabel, -11);
- $mnemonic = '';
- $addressingType = -1;
- $isInvalid = 1;
- }
- $isDataByte = true;
- $dataStr = 'Data';
- }
- }
- else
- {
- $theOldLabel = ''; // Reset 'theOldLabel' when we are no longer in a known data byte
- }
-
-
- $readBytes = $byteLen - 1;
- $bytes = '';
- $byteStr = '';
- $trailer = '';
- $hextext = dechex_pad($opcode);
-
- $byteArr = array($hextext);
-
-
- // read 1 or 2 byte paramters for the opcode
- if ($readBytes > 0)
- {
- if ($pass >= 1)
- {
- if ($cdlFilename !== false)
- {
- $cdlPos = ftell($cdlFile);
- $didMoveCdlPtr = false;
- }
- // check to see if a label exists in this opcode.. if so then usually it's data
- for ($i = 1; $i <= $readBytes; $i++)
- {
- if (isCounterLabel($counter + $i, $oldLabels)
- //if (isset($oldLabels[dechex_pad($counter + $i)])
- || $counter + $i >= 0xFFFA
- || ($counter + $i >= $fileLength)
- || ($usingMapper2 && $headerInfo && $headerInfo->mapper == 2 && $counter + $i > 0xBFFF && $prgBank < $headerInfo->prg - 1)
- ) // if counter in the vectors
-
- {
- $invalidCounter = 0;
- $readBytes = $i - 1;
- $isInvalid = 1;
- $byteLen = $i;
- $addressingType = -1;
- continue;
- }
-
- // if this byte marked as data in cdl; check if next bytes are code
- if ($cdlFilename !== false && $isDataByte)
- {
- $newCdlByte = ord(fread($cdlFile, 1));
- $didMoveCdlPtr = true;
- if ($newCdlByte & bindec('00000001'))
- {
- $invalidCounter = 0;
- $readBytes = $i - 1;
- $isInvalid = 1;
- $byteLen = $i;
- $addressingType = -1;
- continue;
- }
- }
- }
-
- if ($didMoveCdlPtr && $cdlFilename !== false)
- {
- fseek($cdlFile, $cdlPos);
- }
-
- }
-
- if ($readBytes > 0) // if readbytes is still > 0 after above
- {
- $bytes = fread($file, $readBytes);
-
- if ($cdlFilename !== false)
- {
- $cdlBytes = fread($cdlFile, $readBytes);
- }
-
- for($j = 0; $j < $readBytes; $j++)
- {
- $byteArr[] = dechex_pad(ord($bytes[$j]));
- $hextext .= ' ' . $byteArr[$j+1];
- }
-
- if ($addressingType == 12)
- {
- $byteStr = (isset($byteArr[1]) ? $byteArr[1]:'') . $byteArr[0];
- $byteStr = dechex_pad(hexdec($byteStr) + 1);
- //echo " $counter $addressingType $byteStr ";
- //print_r($byteArr);
- }
- elseif ($addressingType == 11)
- {
- $byteStr = (isset($byteArr[1]) ? $byteArr[1]:'') . $byteArr[0];
- }
- else
- {
- $byteStr = (isset($byteArr[2]) ? $byteArr[2]:'') . $byteArr[1];
- }
- }
- }
-
- // ASM6 seems to do some optimization and won't allow absolute addr mode
- // when using $00xx.. it turns it into $xx
- // so instead we'll use .hex
- if ($readBytes == 2
- && substr($byteStr,0,2) == "00"
- && $addressingType > 0
- && $addressingType < 9
- // && $addressingType != 9
- && $addressingType != 3)
- {
- $isInvalid = 1;
- $invalidText = "Bad Addr Mode";
- }
-
- // add label to list
- $oldByteStr = $byteStr;
- $lbl = '$';
-
- if ($addressingType > 0
- && isValidLabel($byteStr)
- && !($ignoreWrites && substr($mnemonic,0,2) == 'ST' && ($byteStr < 0x8000))) // do not add labels when writing to PRG
- {
-
- $lbl = '__';
-
- if ($pass < $lastPass && $isInvalid !== 1)
- {
-
- addValidLabel($byteStr, $labels);
- }
-
- }
-
- $oldByteStr = $byteStr;
-
- // $byteStrDec = (dechex_pad($byteStr);
- $newByteStr = $lbl . $byteStr;
-
- if (isset($oldLabels[$byteStr]) && $lbl !== '')
- {
- $oldLabel = $oldLabels[$byteStr];
-
- $newByteStr = $oldLabel === true
- ? $newByteStr
- : $oldLabel;
- }
-
- // lets check for various addressing types to figure out how to format the text
- switch($addressingType)
- {
-
- case 0: // Implicit/Accumulator/Immediate
- $byteStr = ($readBytes > 0 ? '#$' . $byteStr : '');
- break;
-
- case 12:
- case 11:
- case 10:
- if (!$isInvalid)
- { addValidLabel($byteStr, $prgLabels);
- }
- case 1: // Absolute
- case 4: // Zero Page
-
- $byteStr = $newByteStr;
-
- if ($addressingType == 12)
- {
- $byteStr .= "-1";
- }
-
- break;
-
- case 2: // Absolute X
- case 5: // Zero Page X
- $byteStr = $newByteStr . ',x';
- break;
-
- case 3: // Absolute Y
- case 6: // Zero Page Y
- $byteStr = $newByteStr . ',y';
- break;
-
- case 7: // Indrect X
- $byteStr = '(' . $newByteStr . ',x)';
- break;
-
- case 8: // Indirect Y
- $byteStr = '(' . $newByteStr . '),y';
- break;
-
- case 9: // Indirect Jump
- $byteStr = '(' . $newByteStr . ')';
- break;
-
- }
-
- // now lets cover specific mnemonics
-
- switch($mnemonic)
- {
- // handle branches
- case 'BCC':
- case 'BCS':
- case 'BEQ':
- case 'BMI':
- case 'BNE':
- case 'BPL':
- case 'BVC':
- case 'BVS':
-
- $addr = addressOffset($counter, $oldByteStr );
-
- $isInvalidBranch = false;
-
- if ($pass < $lastPass && !$isInvalid && !$isInvalidBranch)
- {
- addValidLabel($addr, $labels);
- addValidLabel($addr, $prgLabels);
- }
-
- if (!$isInvalidBranch && isValidLabel($addr))
- { if (isset($labels[$addr]) && $labels[$addr] !== true)
- {
- $byteStr = $labels[$addr];
- }
- else
- {
-
- $byteStr = '__' . $addr;
- }
- }
- else
- {
- $isInvalid = true;
- $invalidText = "Illegal Branch";
- }
-
- break;
-
- // add some space after RTS/JMP
- case 'RTS':
- case 'RTI':
- case 'JMP':
- if (!$isInvalid)
- { $trailer = "\n" . commentLine();
- $didDrawLine = true;
- }
- break;
-
- }
-
- // only deal with output on last pass
- if ($pass == $lastPass)
- {
- if ($isInvalid)
- {
- $oldMnemonicStr = $addressingType == -1 ? $dataStr : ($invalidText . " - " . $mnemonic .' '. $byteStr);
- $mnemonic = ".hex";
- $byteStr = $hextext;
-
- }
- $counter_pad = dechex_pad($counter);
- if (array_key_exists($counter_pad, $oldLabels))
- {
- $leng = 1;
- if (is_array($oldLabels[$counter_pad]))
- { $leng = count($oldLabels[$counter_pad]);
-
- }
-
-
- for ($i = 0; $i < $leng; $i++)
- {
- if (is_array($oldLabels[$counter_pad]))
- {
- $theLabel = $oldLabels[$counter_pad][$i];
- }
- else
- {
- $theLabel = $oldLabels[$counter_pad] === true
- ? '__' . $counter_pad
- : $oldLabels[$counter_pad];
-
- }
-
- // if label has a + or - in it but doesn't start with one
- // then don't show it
- // if not 0 or false
- if (strpos($theLabel, '+') || strpos($theLabel, '-'))
- {
- $theText .= LEFT_MARGIN;
- continue;
- }
-
- switch($theLabel)
- {
- case "irq":
- $theText .= commentHeader("irq/brk vector", !($oldDidDrawLine || $didDrawLine), !($oldDidDrawLine || $didDrawLine));
- break;
-
- case "nmi":
- case "reset":
- $theText .= commentHeader("$theLabel vector", !($oldDidDrawLine || $didDrawLine), !($oldDidDrawLine || $didDrawLine));
- break;
-
- }
-
- if (strlen($theLabel) >= $marginLen - 1)
- {
- $theText .= ($oldDidDrawLine || $didDrawLine || ($counter == $origin) ? '' : "\n")
- . "$theLabel:\n" . LEFT_MARGIN;
- }
- else
- {
- $theText .= str_pad($theLabel . ':', $marginLen);
- }
-
- }
-
- }
- else
- {
- $theText .= LEFT_MARGIN;
- }
-
- //$line = array_key_exists(dechex_pad($counter), $oldLabels) ? '__' . dechex_pad($counter) .':' : ' ';
- $line = '';
- $line .= ($useLowerCase ? strtolower($mnemonic) : $mnemonic) .' '. $byteStr;
-
- //$labelLen
- $line = str_pad($line, 30 - $marginLen + $labelLen);
-
- $line .= ' ; $' . dechex_pad($counter) . ": " .$hextext;
- $line = str_pad($line, ($isDataByte ? 54 : 50) - $marginLen + $labelLen);
- $line .= ($isInvalid ? $oldMnemonicStr : '');
- $line .= "\n" . $trailer;
-
- $theText .= $line;
-
- }
- $counter += $byteLen;
- $oldDidDrawLine = $didDrawLine;
- } // end line by line loop
-
-
-
- if ($pass < $lastPass && $oldLabels !== false && $labels == $oldLabels)
- {
- $lastPass = $pass + 1;
- }
- /*elseif($pass < $lastPass)
- {
- echo "$pass < $lastPass && $oldLabels !== false && $labels == $oldLabels (" . print_r($labels == $oldLabels,true);
- file_put_contents('out', print_r($labels,true) . print_r($oldLabels, true));
- file_put_contents('out2', print_r(array_diff_assoc($labels, $oldLabels),true));
- }*/
-
- if ($pass < $lastPass)
- {
-
- $oldLabels = $labels;
- $oldPrgLabels = $prgLabels;
-
- rewind($file);
- }
-
- echo "complete\n";
- $pass++;
- }
-
- if ($includeChr && $headerInfo !== false)
- {
-
- fseek($file, $oldPrg * 0x4000 + 0x10);
-
- $chr = '';
-
-
- while (!feof($file))
- {
- $chr .= fread($file,1024);
-
- }
-
- $theText .= "\n" . commentLine();
- $theText .= "; CHR-ROM";
- $theText .= "\n" . commentLine();
-
- $incLine = LEFT_MARGIN . ".incbin " . $shortname.'.chr';
- $theText .= str_pad($incLine, 30 + $labelLen) . " ; Include CHR-ROM\n";
-
- file_put_contents($shortname.'.chr', $chr);
- echo "\nCHR-ROM exported as $shortname.chr";
-
-
- }elseif ($includeChr)
- {
- echo "\nCHR-ROM cannot be exported without iNES header data";
- if ($ignoreHeader)
- {
- "\nTry disabling -ignoreheader if you wish to export CHR-ROM data";
- }
- }
-
- file_put_contents($shortname.'.asm', $theText);
-
-
- $time_end = microtime(true);
- $time = round($time_end - $time_start,3);
-
- echo "\nDisassembly $shortname.asm generated in $time seconds\n\n";
-