2006-08-01 04:44:47 +00:00
/// \file
/// \brief 6502 assembler and disassembler
# include "types.h"
2006-08-01 05:50:19 +00:00
# include "utils/xstring.h"
2024-02-23 09:38:05 +00:00
# include "utils/StringBuilder.h"
2006-08-01 04:44:47 +00:00
# include "debug.h"
# include "asm.h"
# include "x6502.h"
2013-04-13 02:52:13 +00:00
# include <cstring>
# include <cstdlib>
# include <cstdio>
2006-08-01 04:44:47 +00:00
///assembles the string to an instruction located at addr, storing opcodes in output buffer
int Assemble ( unsigned char * output , int addr , char * str ) {
//unsigned char opcode[3] = { 0,0,0 };
output [ 0 ] = output [ 1 ] = output [ 2 ] = 0 ;
char astr [ 128 ] , ins [ 4 ] ;
2012-10-21 16:40:04 +00:00
int len = strlen ( str ) ;
2021-04-28 00:22:39 +00:00
if ( ( ! len ) | | ( len > 127 ) ) return 1 ;
2006-08-01 04:44:47 +00:00
strcpy ( astr , str ) ;
str_ucase ( astr ) ;
sscanf ( astr , " %3s " , ins ) ; //get instruction
if ( strlen ( ins ) ! = 3 ) return 1 ;
strcpy ( astr , strstr ( astr , ins ) + 3 ) ; //heheh, this is probably a bad idea, but let's do it anyway!
if ( ( astr [ 0 ] ! = ' ' ) & & ( astr [ 0 ] ! = 0 ) ) return 1 ;
//remove all whitespace
str_strip ( astr , STRIP_SP | STRIP_TAB | STRIP_CR | STRIP_LF ) ;
//repair syntax
chr_replace ( astr , ' [ ' , ' ( ' ) ; //brackets
chr_replace ( astr , ' ] ' , ' ) ' ) ;
chr_replace ( astr , ' { ' , ' ( ' ) ;
chr_replace ( astr , ' } ' , ' ) ' ) ;
chr_replace ( astr , ' ; ' , 0 ) ; //comments
str_replace ( astr , " 0X " , " $ " ) ; //miscellaneous
//This does the following:
// 1) Sets opcode[0] on success, else returns 1.
// 2) Parses text in *astr to build the rest of the assembled
// data in 'opcode', else returns 1 on error.
2012-10-21 16:40:04 +00:00
2006-08-01 04:44:47 +00:00
if ( ! strlen ( astr ) ) {
//Implied instructions
if ( ! strcmp ( ins , " BRK " ) ) output [ 0 ] = 0x00 ;
else if ( ! strcmp ( ins , " PHP " ) ) output [ 0 ] = 0x08 ;
else if ( ! strcmp ( ins , " ASL " ) ) output [ 0 ] = 0x0A ;
else if ( ! strcmp ( ins , " CLC " ) ) output [ 0 ] = 0x18 ;
else if ( ! strcmp ( ins , " PLP " ) ) output [ 0 ] = 0x28 ;
else if ( ! strcmp ( ins , " ROL " ) ) output [ 0 ] = 0x2A ;
else if ( ! strcmp ( ins , " SEC " ) ) output [ 0 ] = 0x38 ;
else if ( ! strcmp ( ins , " RTI " ) ) output [ 0 ] = 0x40 ;
else if ( ! strcmp ( ins , " PHA " ) ) output [ 0 ] = 0x48 ;
else if ( ! strcmp ( ins , " LSR " ) ) output [ 0 ] = 0x4A ;
else if ( ! strcmp ( ins , " CLI " ) ) output [ 0 ] = 0x58 ;
else if ( ! strcmp ( ins , " RTS " ) ) output [ 0 ] = 0x60 ;
else if ( ! strcmp ( ins , " PLA " ) ) output [ 0 ] = 0x68 ;
else if ( ! strcmp ( ins , " ROR " ) ) output [ 0 ] = 0x6A ;
else if ( ! strcmp ( ins , " SEI " ) ) output [ 0 ] = 0x78 ;
else if ( ! strcmp ( ins , " DEY " ) ) output [ 0 ] = 0x88 ;
else if ( ! strcmp ( ins , " TXA " ) ) output [ 0 ] = 0x8A ;
else if ( ! strcmp ( ins , " TYA " ) ) output [ 0 ] = 0x98 ;
else if ( ! strcmp ( ins , " TXS " ) ) output [ 0 ] = 0x9A ;
else if ( ! strcmp ( ins , " TAY " ) ) output [ 0 ] = 0xA8 ;
else if ( ! strcmp ( ins , " TAX " ) ) output [ 0 ] = 0xAA ;
else if ( ! strcmp ( ins , " CLV " ) ) output [ 0 ] = 0xB8 ;
else if ( ! strcmp ( ins , " TSX " ) ) output [ 0 ] = 0xBA ;
else if ( ! strcmp ( ins , " INY " ) ) output [ 0 ] = 0xC8 ;
else if ( ! strcmp ( ins , " DEX " ) ) output [ 0 ] = 0xCA ;
else if ( ! strcmp ( ins , " CLD " ) ) output [ 0 ] = 0xD8 ;
else if ( ! strcmp ( ins , " INX " ) ) output [ 0 ] = 0xE8 ;
else if ( ! strcmp ( ins , " NOP " ) ) output [ 0 ] = 0xEA ;
else if ( ! strcmp ( ins , " SED " ) ) output [ 0 ] = 0xF8 ;
else return 1 ;
}
else {
//Instructions with Operands
if ( ! strcmp ( ins , " ORA " ) ) output [ 0 ] = 0x01 ;
else if ( ! strcmp ( ins , " ASL " ) ) output [ 0 ] = 0x06 ;
else if ( ! strcmp ( ins , " BPL " ) ) output [ 0 ] = 0x10 ;
else if ( ! strcmp ( ins , " JSR " ) ) output [ 0 ] = 0x20 ;
else if ( ! strcmp ( ins , " AND " ) ) output [ 0 ] = 0x21 ;
else if ( ! strcmp ( ins , " BIT " ) ) output [ 0 ] = 0x24 ;
else if ( ! strcmp ( ins , " ROL " ) ) output [ 0 ] = 0x26 ;
else if ( ! strcmp ( ins , " BMI " ) ) output [ 0 ] = 0x30 ;
else if ( ! strcmp ( ins , " EOR " ) ) output [ 0 ] = 0x41 ;
else if ( ! strcmp ( ins , " LSR " ) ) output [ 0 ] = 0x46 ;
else if ( ! strcmp ( ins , " JMP " ) ) output [ 0 ] = 0x4C ;
else if ( ! strcmp ( ins , " BVC " ) ) output [ 0 ] = 0x50 ;
else if ( ! strcmp ( ins , " ADC " ) ) output [ 0 ] = 0x61 ;
else if ( ! strcmp ( ins , " ROR " ) ) output [ 0 ] = 0x66 ;
else if ( ! strcmp ( ins , " BVS " ) ) output [ 0 ] = 0x70 ;
else if ( ! strcmp ( ins , " STA " ) ) output [ 0 ] = 0x81 ;
else if ( ! strcmp ( ins , " STY " ) ) output [ 0 ] = 0x84 ;
else if ( ! strcmp ( ins , " STX " ) ) output [ 0 ] = 0x86 ;
else if ( ! strcmp ( ins , " BCC " ) ) output [ 0 ] = 0x90 ;
else if ( ! strcmp ( ins , " LDY " ) ) output [ 0 ] = 0xA0 ;
else if ( ! strcmp ( ins , " LDA " ) ) output [ 0 ] = 0xA1 ;
else if ( ! strcmp ( ins , " LDX " ) ) output [ 0 ] = 0xA2 ;
else if ( ! strcmp ( ins , " BCS " ) ) output [ 0 ] = 0xB0 ;
else if ( ! strcmp ( ins , " CPY " ) ) output [ 0 ] = 0xC0 ;
else if ( ! strcmp ( ins , " CMP " ) ) output [ 0 ] = 0xC1 ;
else if ( ! strcmp ( ins , " DEC " ) ) output [ 0 ] = 0xC6 ;
else if ( ! strcmp ( ins , " BNE " ) ) output [ 0 ] = 0xD0 ;
else if ( ! strcmp ( ins , " CPX " ) ) output [ 0 ] = 0xE0 ;
else if ( ! strcmp ( ins , " SBC " ) ) output [ 0 ] = 0xE1 ;
else if ( ! strcmp ( ins , " INC " ) ) output [ 0 ] = 0xE6 ;
else if ( ! strcmp ( ins , " BEQ " ) ) output [ 0 ] = 0xF0 ;
else return 1 ;
{
//Parse Operands
// It's not the sexiest thing ever, but it works well enough!
//TODO:
// Add branches.
// Fix certain instructions. (Setting bits is not 100% perfect.)
// Fix instruction/operand matching. (Instructions like "jmp ($94),Y" are no good!)
// Optimizations?
int tmpint ;
char tmpchr , tmpstr [ 20 ] ;
if ( sscanf ( astr , " #$%2X%c " , & tmpint , & tmpchr ) = = 1 ) { //#Immediate
switch ( output [ 0 ] ) {
case 0x20 : case 0x4C : //Jumps
case 0x10 : case 0x30 : case 0x50 : case 0x70 : //Branches
case 0x90 : case 0xB0 : case 0xD0 : case 0xF0 :
case 0x06 : case 0x24 : case 0x26 : case 0x46 : //Other instructions incapable of #Immediate
case 0x66 : case 0x81 : case 0x84 : case 0x86 :
case 0xC6 : case 0xE6 :
return 1 ;
default :
//cheap hack for certain instructions
switch ( output [ 0 ] ) {
case 0xA0 : case 0xA2 : case 0xC0 : case 0xE0 :
break ;
default :
output [ 0 ] | = 0x08 ;
break ;
}
output [ 1 ] = tmpint ;
break ;
}
}
else if ( sscanf ( astr , " $%4X%c " , & tmpint , & tmpchr ) = = 1 ) { //Absolute, Zero Page, Branch, or Jump
switch ( output [ 0 ] ) {
case 0x20 : case 0x4C : //Jumps
output [ 1 ] = ( tmpint & 0xFF ) ;
output [ 2 ] = ( tmpint > > 8 ) ;
break ;
case 0x10 : case 0x30 : case 0x50 : case 0x70 : //Branches
case 0x90 : case 0xB0 : case 0xD0 : case 0xF0 :
tmpint - = ( addr + 2 ) ;
if ( ( tmpint < - 128 ) | | ( tmpint > 127 ) ) return 1 ;
output [ 1 ] = ( tmpint & 0xFF ) ;
break ;
//return 1; //FIX ME
default :
if ( tmpint > 0xFF ) { //Absolute
output [ 0 ] | = 0x0C ;
output [ 1 ] = ( tmpint & 0xFF ) ;
output [ 2 ] = ( tmpint > > 8 ) ;
}
else { //Zero Page
output [ 0 ] | = 0x04 ;
output [ 1 ] = ( tmpint & 0xFF ) ;
}
break ;
}
}
else if ( sscanf ( astr , " $%4X%s " , & tmpint , tmpstr ) = = 2 ) { //Absolute,X, Zero Page,X, Absolute,Y or Zero Page,Y
if ( ! strcmp ( tmpstr , " ,X " ) ) { //Absolute,X or Zero Page,X
switch ( output [ 0 ] ) {
case 0x20 : case 0x4C : //Jumps
case 0x10 : case 0x30 : case 0x50 : case 0x70 : //Branches
case 0x90 : case 0xB0 : case 0xD0 : case 0xF0 :
case 0x24 : case 0x86 : case 0xA2 : case 0xC0 : //Other instructions incapable of Absolute,X or Zero Page,X
case 0xE0 :
return 1 ;
default :
if ( tmpint > 0xFF ) { //Absolute
if ( output [ 0 ] = = 0x84 ) return 1 ; //No STY Absolute,X!
output [ 0 ] | = 0x1C ;
output [ 1 ] = ( tmpint & 0xFF ) ;
output [ 2 ] = ( tmpint > > 8 ) ;
}
else { //Zero Page
output [ 0 ] | = 0x14 ;
output [ 1 ] = ( tmpint & 0xFF ) ;
}
break ;
}
}
else if ( ! strcmp ( tmpstr , " ,Y " ) ) { //Absolute,Y or Zero Page,Y
switch ( output [ 0 ] ) {
case 0x20 : case 0x4C : //Jumps
case 0x10 : case 0x30 : case 0x50 : case 0x70 : //Branches
case 0x90 : case 0xB0 : case 0xD0 : case 0xF0 :
case 0x06 : case 0x24 : case 0x26 : case 0x46 : //Other instructions incapable of Absolute,Y or Zero Page,Y
case 0x66 : case 0x84 : case 0x86 : case 0xA0 :
case 0xC0 : case 0xC6 : case 0xE0 : case 0xE6 :
return 1 ;
case 0xA2 : //cheap hack for LDX
output [ 0 ] | = 0x04 ;
default :
if ( tmpint > 0xFF ) { //Absolute
if ( output [ 0 ] = = 0x86 ) return 1 ; //No STX Absolute,Y!
output [ 0 ] | = 0x18 ;
output [ 1 ] = ( tmpint & 0xFF ) ;
output [ 2 ] = ( tmpint > > 8 ) ;
}
else { //Zero Page
2012-03-17 16:29:56 +00:00
if ( ( output [ 0 ] ! = 0x86 ) & & ( output [ 0 ] ! = 0xA2 ) ) return 1 ; //only STX and LDX Absolute,Y!
2006-08-01 04:44:47 +00:00
output [ 0 ] | = 0x10 ;
output [ 1 ] = ( tmpint & 0xFF ) ;
}
break ;
}
}
else return 1 ;
}
else if ( sscanf ( astr , " ($%4X%s " , & tmpint , tmpstr ) = = 2 ) { //Jump (Indirect), (Indirect,X) or (Indirect),Y
switch ( output [ 0 ] ) {
case 0x20 : //Jumps
case 0x10 : case 0x30 : case 0x50 : case 0x70 : //Branches
case 0x90 : case 0xB0 : case 0xD0 : case 0xF0 :
case 0x06 : case 0x24 : case 0x26 : case 0x46 : //Other instructions incapable of Jump (Indirect), (Indirect,X) or (Indirect),Y
case 0x66 : case 0x84 : case 0x86 : case 0xA0 :
case 0xA2 : case 0xC0 : case 0xC6 : case 0xE0 :
case 0xE6 :
return 1 ;
default :
if ( ( ! strcmp ( tmpstr , " ) " ) ) & & ( output [ 0 ] = = 0x4C ) ) { //Jump (Indirect)
output [ 0 ] = 0x6C ;
output [ 1 ] = ( tmpint & 0xFF ) ;
output [ 2 ] = ( tmpint > > 8 ) ;
}
else if ( ( ! strcmp ( tmpstr , " ,X) " )) && (tmpint <= 0xFF) && (output[0] != 0x4C)) { //(Indirect,X)
output [ 1 ] = ( tmpint & 0xFF ) ;
}
else if ( ( ! strcmp ( tmpstr , " ) , Y " )) && (tmpint <= 0xFF) && (output[0] != 0x4C)) { //(Indirect),Y
output [ 0 ] | = 0x10 ;
output [ 1 ] = ( tmpint & 0xFF ) ;
}
else return 1 ;
break ;
}
}
else return 1 ;
}
}
return 0 ;
}
///disassembles the opcodes in the buffer assuming the provided address. Uses GetMem() and 6502 current registers to query referenced values. returns a static string buffer.
char * Disassemble ( int addr , uint8 * opcode ) {
2024-02-23 09:38:05 +00:00
static char str [ 64 ] = { 0 } ;
const char * chr ;
char indReg ;
2006-08-01 04:44:47 +00:00
uint16 tmp , tmp2 ;
2024-02-23 09:38:05 +00:00
StringBuilder sb ( str ) ;
2006-08-01 04:44:47 +00:00
//these may be replaced later with passed-in values to make a lighter-weight disassembly mode that may not query the referenced values
# define RX (X.X)
# define RY (X.Y)
switch ( opcode [ 0 ] ) {
# define relative(a) { \
if ( ( ( a ) = opcode [ 1 ] ) & 0x80 ) ( a ) = addr - ( ( ( a ) - 1 ) ^ 0xFF ) ; \
else ( a ) + = addr ; \
}
# define absolute(a) { \
( a ) = opcode [ 1 ] | opcode [ 2 ] < < 8 ; \
}
# define zpIndex(a,i) { \
2017-04-29 13:52:53 +00:00
( a ) = ( opcode [ 1 ] + ( i ) ) & 0xFF ; \
2006-08-01 04:44:47 +00:00
}
# define indirectX(a) { \
( a ) = ( opcode [ 1 ] + RX ) & 0xFF ; \
2014-11-03 20:48:24 +00:00
( a ) = GetMem ( ( a ) ) | ( GetMem ( ( ( a ) + 1 ) & 0xff ) ) < < 8 ; \
2006-08-01 04:44:47 +00:00
}
# define indirectY(a) { \
2014-11-03 20:48:24 +00:00
( a ) = GetMem ( opcode [ 1 ] ) | ( GetMem ( ( opcode [ 1 ] + 1 ) & 0xff ) ) < < 8 ; \
2006-08-01 04:44:47 +00:00
( a ) + = RY ; \
}
2014-03-14 18:03:04 +00:00
# ifdef BRK_3BYTE_HACK
case 0x00 :
2024-02-23 09:38:05 +00:00
sb < < " BRK " < < sb_hex ( opcode [ 1 ] , 2 ) < < ' ' < < sb_hex ( opcode [ 2 ] , 2 ) ;
2014-03-14 18:03:04 +00:00
break ;
# else
case 0x00 : strcpy ( str , " BRK " ) ; break ;
# endif
2006-08-01 04:44:47 +00:00
//odd, 1-byte opcodes
case 0x08 : strcpy ( str , " PHP " ) ; break ;
case 0x0A : strcpy ( str , " ASL " ) ; break ;
case 0x18 : strcpy ( str , " CLC " ) ; break ;
case 0x28 : strcpy ( str , " PLP " ) ; break ;
case 0x2A : strcpy ( str , " ROL " ) ; break ;
case 0x38 : strcpy ( str , " SEC " ) ; break ;
case 0x40 : strcpy ( str , " RTI " ) ; break ;
case 0x48 : strcpy ( str , " PHA " ) ; break ;
case 0x4A : strcpy ( str , " LSR " ) ; break ;
case 0x58 : strcpy ( str , " CLI " ) ; break ;
case 0x60 : strcpy ( str , " RTS " ) ; break ;
case 0x68 : strcpy ( str , " PLA " ) ; break ;
case 0x6A : strcpy ( str , " ROR " ) ; break ;
case 0x78 : strcpy ( str , " SEI " ) ; break ;
case 0x88 : strcpy ( str , " DEY " ) ; break ;
case 0x8A : strcpy ( str , " TXA " ) ; break ;
case 0x98 : strcpy ( str , " TYA " ) ; break ;
case 0x9A : strcpy ( str , " TXS " ) ; break ;
case 0xA8 : strcpy ( str , " TAY " ) ; break ;
case 0xAA : strcpy ( str , " TAX " ) ; break ;
case 0xB8 : strcpy ( str , " CLV " ) ; break ;
case 0xBA : strcpy ( str , " TSX " ) ; break ;
case 0xC8 : strcpy ( str , " INY " ) ; break ;
case 0xCA : strcpy ( str , " DEX " ) ; break ;
case 0xD8 : strcpy ( str , " CLD " ) ; break ;
case 0xE8 : strcpy ( str , " INX " ) ; break ;
case 0xEA : strcpy ( str , " NOP " ) ; break ;
case 0xF8 : strcpy ( str , " SED " ) ; break ;
//(Indirect,X)
2024-02-23 09:38:05 +00:00
case 0x01 : chr = " ORA " ; goto _indirectx ;
case 0x21 : chr = " AND " ; goto _indirectx ;
case 0x41 : chr = " EOR " ; goto _indirectx ;
case 0x61 : chr = " ADC " ; goto _indirectx ;
case 0x81 : chr = " STA " ; goto _indirectx ;
case 0xA1 : chr = " LDA " ; goto _indirectx ;
case 0xC1 : chr = " CMP " ; goto _indirectx ;
case 0xE1 : chr = " SBC " ; goto _indirectx ;
2006-08-01 04:44:47 +00:00
_indirectx :
indirectX ( tmp ) ;
2024-02-23 09:38:05 +00:00
indReg = ' X ' ;
_indirect :
sb < < chr < < " ( " < < sb_addr ( opcode [ 1 ] , 2 ) < < ' , ' < < indReg < < " ) @ " < < sb_addr ( tmp ) < < " = " < < sb_lit ( GetMem ( tmp ) ) ;
2006-08-01 04:44:47 +00:00
break ;
//Zero Page
2024-02-23 09:38:05 +00:00
case 0x05 : chr = " ORA " ; goto _zeropage ;
case 0x06 : chr = " ASL " ; goto _zeropage ;
case 0x24 : chr = " BIT " ; goto _zeropage ;
case 0x25 : chr = " AND " ; goto _zeropage ;
case 0x26 : chr = " ROL " ; goto _zeropage ;
case 0x45 : chr = " EOR " ; goto _zeropage ;
case 0x46 : chr = " LSR " ; goto _zeropage ;
case 0x65 : chr = " ADC " ; goto _zeropage ;
case 0x66 : chr = " ROR " ; goto _zeropage ;
case 0x84 : chr = " STY " ; goto _zeropage ;
case 0x85 : chr = " STA " ; goto _zeropage ;
case 0x86 : chr = " STX " ; goto _zeropage ;
case 0xA4 : chr = " LDY " ; goto _zeropage ;
case 0xA5 : chr = " LDA " ; goto _zeropage ;
case 0xA6 : chr = " LDX " ; goto _zeropage ;
case 0xC4 : chr = " CPY " ; goto _zeropage ;
case 0xC5 : chr = " CMP " ; goto _zeropage ;
case 0xC6 : chr = " DEC " ; goto _zeropage ;
case 0xE4 : chr = " CPX " ; goto _zeropage ;
case 0xE5 : chr = " SBC " ; goto _zeropage ;
case 0xE6 : chr = " INC " ; goto _zeropage ;
2006-08-01 04:44:47 +00:00
_zeropage :
// ################################## Start of SP CODE ###########################
2017-04-29 13:52:53 +00:00
// Change width to %04X // don't!
2024-02-23 09:38:05 +00:00
sb < < chr < < ' ' < < sb_addr ( opcode [ 1 ] , 2 ) < < " = " < < sb_lit ( GetMem ( opcode [ 1 ] ) ) ;
2006-08-01 04:44:47 +00:00
// ################################## End of SP CODE ###########################
break ;
//#Immediate
2024-02-23 09:38:05 +00:00
case 0x09 : chr = " ORA " ; goto _immediate ;
case 0x29 : chr = " AND " ; goto _immediate ;
case 0x49 : chr = " EOR " ; goto _immediate ;
case 0x69 : chr = " ADC " ; goto _immediate ;
//case 0x89: chr = "STA"; goto _immediate; //baka, no STA #imm!!
case 0xA0 : chr = " LDY " ; goto _immediate ;
case 0xA2 : chr = " LDX " ; goto _immediate ;
case 0xA9 : chr = " LDA " ; goto _immediate ;
case 0xC0 : chr = " CPY " ; goto _immediate ;
case 0xC9 : chr = " CMP " ; goto _immediate ;
case 0xE0 : chr = " CPX " ; goto _immediate ;
case 0xE9 : chr = " SBC " ; goto _immediate ;
2006-08-01 04:44:47 +00:00
_immediate :
2024-02-23 09:38:05 +00:00
sb < < chr < < ' ' < < sb_lit ( opcode [ 1 ] ) ;
2006-08-01 04:44:47 +00:00
break ;
//Absolute
2024-02-23 09:38:05 +00:00
case 0x0D : chr = " ORA " ; goto _absolute ;
case 0x0E : chr = " ASL " ; goto _absolute ;
case 0x2C : chr = " BIT " ; goto _absolute ;
case 0x2D : chr = " AND " ; goto _absolute ;
case 0x2E : chr = " ROL " ; goto _absolute ;
case 0x4D : chr = " EOR " ; goto _absolute ;
case 0x4E : chr = " LSR " ; goto _absolute ;
case 0x6D : chr = " ADC " ; goto _absolute ;
case 0x6E : chr = " ROR " ; goto _absolute ;
case 0x8C : chr = " STY " ; goto _absolute ;
case 0x8D : chr = " STA " ; goto _absolute ;
case 0x8E : chr = " STX " ; goto _absolute ;
case 0xAC : chr = " LDY " ; goto _absolute ;
case 0xAD : chr = " LDA " ; goto _absolute ;
case 0xAE : chr = " LDX " ; goto _absolute ;
case 0xCC : chr = " CPY " ; goto _absolute ;
case 0xCD : chr = " CMP " ; goto _absolute ;
case 0xCE : chr = " DEC " ; goto _absolute ;
case 0xEC : chr = " CPX " ; goto _absolute ;
case 0xED : chr = " SBC " ; goto _absolute ;
case 0xEE : chr = " INC " ; goto _absolute ;
2006-08-01 04:44:47 +00:00
_absolute :
absolute ( tmp ) ;
2024-02-23 09:38:05 +00:00
sb < < chr < < ' ' < < sb_addr ( tmp ) < < " = " < < sb_lit ( GetMem ( tmp ) ) ;
2006-08-01 04:44:47 +00:00
break ;
//branches
2024-02-23 09:38:05 +00:00
case 0x10 : chr = " BPL " ; goto _branch ;
case 0x30 : chr = " BMI " ; goto _branch ;
case 0x50 : chr = " BVC " ; goto _branch ;
case 0x70 : chr = " BVS " ; goto _branch ;
case 0x90 : chr = " BCC " ; goto _branch ;
case 0xB0 : chr = " BCS " ; goto _branch ;
case 0xD0 : chr = " BNE " ; goto _branch ;
case 0xF0 : chr = " BEQ " ; goto _branch ;
2006-08-01 04:44:47 +00:00
_branch :
relative ( tmp ) ;
2024-02-23 09:38:05 +00:00
sb < < chr < < ' ' < < sb_addr ( tmp ) ;
2006-08-01 04:44:47 +00:00
break ;
//(Indirect),Y
2024-02-23 09:38:05 +00:00
case 0x11 : chr = " ORA " ; goto _indirecty ;
case 0x31 : chr = " AND " ; goto _indirecty ;
case 0x51 : chr = " EOR " ; goto _indirecty ;
case 0x71 : chr = " ADC " ; goto _indirecty ;
case 0x91 : chr = " STA " ; goto _indirecty ;
case 0xB1 : chr = " LDA " ; goto _indirecty ;
case 0xD1 : chr = " CMP " ; goto _indirecty ;
case 0xF1 : chr = " SBC " ; goto _indirecty ;
2006-08-01 04:44:47 +00:00
_indirecty :
indirectY ( tmp ) ;
2024-02-23 09:38:05 +00:00
indReg = ' Y ' ;
goto _indirect ;
2006-08-01 04:44:47 +00:00
//Zero Page,X
2024-02-23 09:38:05 +00:00
case 0x15 : chr = " ORA " ; goto _zeropagex ;
case 0x16 : chr = " ASL " ; goto _zeropagex ;
case 0x35 : chr = " AND " ; goto _zeropagex ;
case 0x36 : chr = " ROL " ; goto _zeropagex ;
case 0x55 : chr = " EOR " ; goto _zeropagex ;
case 0x56 : chr = " LSR " ; goto _zeropagex ;
case 0x75 : chr = " ADC " ; goto _zeropagex ;
case 0x76 : chr = " ROR " ; goto _zeropagex ;
case 0x94 : chr = " STY " ; goto _zeropagex ;
case 0x95 : chr = " STA " ; goto _zeropagex ;
case 0xB4 : chr = " LDY " ; goto _zeropagex ;
case 0xB5 : chr = " LDA " ; goto _zeropagex ;
case 0xD5 : chr = " CMP " ; goto _zeropagex ;
case 0xD6 : chr = " DEC " ; goto _zeropagex ;
case 0xF5 : chr = " SBC " ; goto _zeropagex ;
case 0xF6 : chr = " INC " ; goto _zeropagex ;
2006-08-01 04:44:47 +00:00
_zeropagex :
2024-02-23 09:38:05 +00:00
zpIndex ( tmp , RX ) ;
indReg = ' X ' ;
_indexed :
2006-08-01 04:44:47 +00:00
// ################################## Start of SP CODE ###########################
2017-04-29 13:52:53 +00:00
// Change width to %04X // don't!
2024-02-23 09:38:05 +00:00
sb < < chr < < ' ' < < sb_addr ( opcode [ 1 ] , 2 ) < < ' , ' < < indReg < < " @ " < < sb_addr ( tmp ) < < " = " < < sb_lit ( GetMem ( tmp ) ) ;
2006-08-01 04:44:47 +00:00
// ################################## End of SP CODE ###########################
break ;
//Absolute,Y
2024-02-23 09:38:05 +00:00
case 0x19 : chr = " ORA " ; goto _absolutey ;
case 0x39 : chr = " AND " ; goto _absolutey ;
case 0x59 : chr = " EOR " ; goto _absolutey ;
case 0x79 : chr = " ADC " ; goto _absolutey ;
case 0x99 : chr = " STA " ; goto _absolutey ;
case 0xB9 : chr = " LDA " ; goto _absolutey ;
case 0xBE : chr = " LDX " ; goto _absolutey ;
case 0xD9 : chr = " CMP " ; goto _absolutey ;
case 0xF9 : chr = " SBC " ; goto _absolutey ;
2006-08-01 04:44:47 +00:00
_absolutey :
absolute ( tmp ) ;
2024-02-23 09:38:05 +00:00
tmp2 = ( tmp + RY ) ;
indReg = ' Y ' ;
_absindexed :
sb < < chr < < ' ' < < sb_addr ( tmp ) < < ' , ' < < indReg < < " @ " < < sb_addr ( tmp2 ) < < " = " < < sb_lit ( GetMem ( tmp2 ) ) ;
2006-08-01 04:44:47 +00:00
break ;
//Absolute,X
2024-02-23 09:38:05 +00:00
case 0x1D : chr = " ORA " ; goto _absolutex ;
case 0x1E : chr = " ASL " ; goto _absolutex ;
case 0x3D : chr = " AND " ; goto _absolutex ;
case 0x3E : chr = " ROL " ; goto _absolutex ;
case 0x5D : chr = " EOR " ; goto _absolutex ;
case 0x5E : chr = " LSR " ; goto _absolutex ;
case 0x7D : chr = " ADC " ; goto _absolutex ;
case 0x7E : chr = " ROR " ; goto _absolutex ;
case 0x9D : chr = " STA " ; goto _absolutex ;
case 0xBC : chr = " LDY " ; goto _absolutex ;
case 0xBD : chr = " LDA " ; goto _absolutex ;
case 0xDD : chr = " CMP " ; goto _absolutex ;
case 0xDE : chr = " DEC " ; goto _absolutex ;
case 0xFD : chr = " SBC " ; goto _absolutex ;
case 0xFE : chr = " INC " ; goto _absolutex ;
2006-08-01 04:44:47 +00:00
_absolutex :
absolute ( tmp ) ;
2024-02-23 09:38:05 +00:00
tmp2 = ( tmp + RX ) ;
indReg = ' X ' ;
goto _absindexed ;
2006-08-01 04:44:47 +00:00
//jumps
2024-02-23 09:38:05 +00:00
case 0x20 : chr = " JSR " ; goto _jump ;
case 0x4C : chr = " JMP " ; goto _jump ;
2006-08-01 04:44:47 +00:00
_jump :
absolute ( tmp ) ;
2024-02-23 09:38:05 +00:00
sb < < chr < < ' ' < < sb_addr ( tmp ) ;
break ;
case 0x6C :
absolute ( tmp ) ;
sb < < " JMP ( " < < sb_addr ( tmp ) ;
sb < < " ) = " < < sb_addr ( GetMem ( tmp ) | GetMem ( tmp + 1 ) < < 8 ) ;
2006-08-01 04:44:47 +00:00
break ;
//Zero Page,Y
2024-02-23 09:38:05 +00:00
case 0x96 : chr = " STX " ; goto _zeropagey ;
case 0xB6 : chr = " LDX " ; goto _zeropagey ;
2006-08-01 04:44:47 +00:00
_zeropagey :
2024-02-23 09:38:05 +00:00
zpIndex ( tmp , RY ) ;
indReg = ' Y ' ;
2006-08-01 04:44:47 +00:00
2024-02-23 09:38:05 +00:00
goto _indexed ;
2006-08-01 04:44:47 +00:00
2024-02-23 09:38:05 +00:00
//UNDEFINED
default : strcpy ( str , " ERROR " ) ; break ;
2006-08-01 04:44:47 +00:00
}
return str ;
2006-08-01 05:50:19 +00:00
}