├── bin └── gb-disasm.exe ├── vs ├── gb-disasm.suo ├── gb-disasm.sln └── gb-disasm.vcxproj ├── make_linux.sh ├── src ├── stdinc.h ├── state.h ├── addr_buff.h ├── io.h ├── rom.h ├── header.h ├── generator.py ├── sops.h ├── main.c ├── opcodes.html └── generated.h ├── test ├── make_gb.sh ├── tetris.asm ├── mario.asm ├── mrdo-asm.py └── drmario.asm └── README.md /bin/gb-disasm.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmuszkow/gb-disasm/HEAD/bin/gb-disasm.exe -------------------------------------------------------------------------------- /vs/gb-disasm.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmuszkow/gb-disasm/HEAD/vs/gb-disasm.suo -------------------------------------------------------------------------------- /make_linux.sh: -------------------------------------------------------------------------------- 1 | ./src/generator.py > ./src/generated.h 2 | mkdir -p bin 3 | gcc ./src/main.c -O2 -Wall -o ./bin/gb-disasm 4 | -------------------------------------------------------------------------------- /src/stdinc.h: -------------------------------------------------------------------------------- 1 | #ifndef __GB_DASM_STDINC_H__ 2 | #define __GB_DASM_STDINC_H__ 3 | 4 | /* stdinc.h: standard includes. */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef unsigned char uint8_t; 11 | typedef unsigned short uint16_t; 12 | typedef unsigned int uint32_t; 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /test/make_gb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # $Id$ 3 | 4 | # This scripts creates a ROM from assembly 5 | 6 | if [ $# -ne 1 ]; then 7 | echo "Usage: $0 " 8 | echo "where GAME is GAME.asm without .asm" 9 | exit 1 10 | fi 11 | 12 | # if file exists 13 | if [ -f "$1.asm" ]; then 14 | rgbasm $1.asm -o $1_reasm.o && rgblink -o $1_reasm.gb $1_reasm.o && rgbfix -v -p 0 $1_reasm.gb && rm $1_reasm.o 15 | else 16 | echo "File $1.asm doesn't exist" 17 | exit 2 18 | fi 19 | -------------------------------------------------------------------------------- /src/state.h: -------------------------------------------------------------------------------- 1 | #ifndef __GB_DASM_STATE_H__ 2 | #define __GB_DASM_STATE_H__ 3 | 4 | /* stack.h: State stack implementation. */ 5 | 6 | /** Bank and pc state after return from control instruction. */ 7 | typedef struct state { 8 | uint16_t pc; 9 | int bank; 10 | struct state* prev; 11 | } state; 12 | 13 | state* state_push(state* top, uint16_t pc, int bank) { 14 | state* el; 15 | el = (state*)malloc(sizeof(state)); 16 | el->pc = pc; 17 | el->bank = bank; 18 | el->prev = top; 19 | return el; 20 | } 21 | 22 | state* state_pop(state* top) { 23 | state* ret; 24 | ret = top->prev; 25 | free(top); 26 | return ret; 27 | } 28 | 29 | void state_free(state* top) { 30 | state* tmp; 31 | while(top) { 32 | tmp = top->prev; 33 | free(top); 34 | top = tmp; 35 | } 36 | } 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | gb-disasm 2 | ========= 3 | 4 | GameBoy ROMs disassembler. 5 | 6 |
Usage: ./gb-disasm <ROM> -s <HEX> -b <BANK> -a -nc -nj
 7 | <ROM> -> obligatory, ROM file to be disassembled
 8 |   -s  -> optional, start address (PC), default is 0x100
 9 |   -e  -> optional, end adress (PC), default is 0x8000
10 |   -b  -> optional, memory bank number, default is 1
11 |   -a  -> optional, print assembly, default is print binary dump
12 |   -nc -> optional, don't follow call instructions, default is to follow
13 |   -nj -> optional, don't follow jump instructions, default is to follow
14 | 15 | It is not finished and can disassemble only parts of the ROMs binaries. 16 | I didn't test it extensively on ROMs with MBC (Memory Bank Controller). 17 | 18 | Most of the code is autogenerated by script (generator.py) that uses 19 | opcodes table (opcodes.html) to generate parsing code in C. 20 | 21 | To compile it on linux, in src directory execute `gcc main.c -O2 -o gb-disasm`. 22 | -------------------------------------------------------------------------------- /vs/gb-disasm.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gb-disasm", "gb-disasm.vcxproj", "{49FB03D9-9CC0-411F-AC16-2FF6E2BDC858}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {49FB03D9-9CC0-411F-AC16-2FF6E2BDC858}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {49FB03D9-9CC0-411F-AC16-2FF6E2BDC858}.Debug|Win32.Build.0 = Debug|Win32 16 | {49FB03D9-9CC0-411F-AC16-2FF6E2BDC858}.Release|Win32.ActiveCfg = Release|Win32 17 | {49FB03D9-9CC0-411F-AC16-2FF6E2BDC858}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /src/addr_buff.h: -------------------------------------------------------------------------------- 1 | #ifndef __GB_DASM_ADDR_LIST_H__ 2 | #define __GB_DASM_ADDR_LIST_H__ 3 | 4 | #include "stdinc.h" 5 | 6 | typedef struct addr_buff { 7 | uint32_t* addr; 8 | int len; 9 | int reserved; 10 | } addr_buff; 11 | 12 | void addr_buff_init(addr_buff* buff) { 13 | /* Initially 1024 elements. */ 14 | buff->addr = (uint32_t*)malloc(4096); 15 | buff->len = 0; 16 | buff->reserved = 1024; 17 | } 18 | 19 | void addr_buff_add(addr_buff* buff, uint32_t addr) { 20 | if(buff->len + 1 < buff->reserved) { 21 | buff->addr[buff->len++] = addr; 22 | } else { 23 | uint32_t* new_addr; 24 | new_addr = (uint32_t*)malloc(buff->reserved << 3); 25 | memcpy(new_addr, buff->addr, buff->len<<2); 26 | free(buff->addr); 27 | buff->addr = new_addr; 28 | buff->reserved <<= 1; 29 | printf("[DEBUG] Resizing to %d\n", buff->reserved); 30 | addr_buff_add(buff, addr); 31 | } 32 | } 33 | 34 | void addr_buff_free(addr_buff* buff) { 35 | if(buff->addr) free(buff->addr); 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /test/tetris.asm: -------------------------------------------------------------------------------- 1 | ; ROM: tetris.gb (MD5: 982ed5d2b12a0377eb14bcdc4123744e) 2 | ; cmd: gb-disasm tetris.gb -s 2041 -nc -a > tetris.asm 3 | ; -s -> start address, determined through bgb debugger 4 | ; -nc -> don't follow call instructions 5 | ; -a -> print assembly 6 | 7 | SECTION "rom0", HOME[0] 8 | 9 | INCBIN "tetris.gb",$0,$2041-$0 10 | genRandom: 11 | LD H,$03 12 | rng_seed: 13 | LDH A,[$04] ; div timer 14 | LD B,A 15 | rng_loop: ; (a%7)*4 16 | XOR A 17 | rng_seven: 18 | DEC B 19 | JR Z,rng_next 20 | INC A 21 | INC A 22 | INC A 23 | INC A 24 | CP $1C 25 | JR Z,rng_loop 26 | JR rng_seven 27 | rng_next: ; avoid generating same number twice 28 | LD D,A 29 | LDH A,[$AE] 30 | LD E,A 31 | DEC H 32 | JR Z,rng_end 33 | OR D 34 | OR C 35 | AND $FC 36 | CP C 37 | JR Z,rng_seed 38 | rng_end: 39 | ;LD A,D ; let's break the generator :) 40 | LD A, $8 41 | LDH [$AE],A 42 | ;LD A,E 43 | LD [$C213],A 44 | CALL $2696 45 | LDH A,[$9A] 46 | LDH [$99],A 47 | RET 48 | 49 | INCBIN "tetris.gb",$2071,$4000-$2071 50 | 51 | SECTION "bank1",DATA,BANK[$1] 52 | INCBIN "tetris.gb",$4000,$4000 53 | -------------------------------------------------------------------------------- /test/mario.asm: -------------------------------------------------------------------------------- 1 | SECTION "rom0", HOME[0] 2 | 3 | ; 0D54 is change level routine 4 | 5 | INCBIN "mario.gb",$0,$1c3c-$0 6 | ; setting life number routine 7 | ; gb-disasm mario.gb -nc -s 1C3C -a 8 | CP $FF 9 | LD A,[$DA15] 10 | JR Z,jmp_1c75 11 | CP $99 12 | JR Z,jmp_1c67 13 | PUSH AF 14 | LD A,$08 15 | LD [$DFE0],A 16 | LDH [$D3],A 17 | POP AF 18 | ; was ADD A,$01, changed to 2xNOP 19 | ; let's do not increase life number if "live up" item found 20 | NOP 21 | NOP 22 | jmp_1c52: 23 | ; DAA was here (check meaning in google), changed to NOP 24 | NOP 25 | LD [$DA15],A ; 0xDA15 is place where lives number is stored 26 | LD A,[$DA15] 27 | LD B,A 28 | AND $0F 29 | LD [$9807],A 30 | LD A,B 31 | AND $F0 32 | SWAP A 33 | LD [$9806],A 34 | jmp_1c67: 35 | XOR A 36 | LD [$C0A3],A 37 | RET 38 | jmp_1c6c: 39 | LD A,$39 40 | LDH [$B3],A 41 | LD [$C0A4],A 42 | JR jmp_1c67 43 | jmp_1c75: 44 | AND A 45 | JR Z,jmp_1c6c 46 | ; SUB $01 was here, changed to 2x NOP 47 | ; let's do not decrease the lives number 48 | NOP 49 | NOP 50 | JR jmp_1c52 51 | 52 | INCBIN "mario.gb",$1c7c,$3d48-$1c7c 53 | ; initial lives count, default 2, lets change to FF 54 | ; gb-disasm mario.gb -nc -nj -s 3D48 -e 3D4B -a 55 | LD A,$FF 56 | LD [HLI],A 57 | 58 | INCBIN "mario.gb",$3d4b,$4000-$3d4b 59 | 60 | SECTION "bank1",DATA,BANK[$1] 61 | INCBIN "mario.gb",$4000,$4000 62 | 63 | SECTION "bank2",DATA,BANK[$2] 64 | INCBIN "mario.gb",$8000,$4000 65 | 66 | SECTION "bank3",DATA,BANK[$3] 67 | INCBIN "mario.gb",$C000,$4000 68 | -------------------------------------------------------------------------------- /src/io.h: -------------------------------------------------------------------------------- 1 | #ifndef __GB_DASM_IO__H__ 2 | #define __GB_DASM_IO__H__ 3 | 4 | /** I/O registers names used for LDH instruction comments. */ 5 | static const char* IO_REGISTER_NAMES[0x80] = { 6 | /* 0x00 */ 7 | "P1/JOYP", 8 | "SB", 9 | "SC", 10 | "UNDEF", 11 | "DIV", 12 | "TIMA", 13 | "TMA", 14 | "TAC", 15 | "UNDEF", 16 | "UNDEF", 17 | "UNDEF", 18 | "UNDEF", 19 | "UNDEF", 20 | "UNDEF", 21 | "UNDEF", 22 | "IF", 23 | /* 0x10 */ 24 | "NR10", 25 | "NR11", 26 | "NR12", 27 | "NR13", 28 | "NR14", 29 | "UNDEF", 30 | "NR21", 31 | "NR22", 32 | "NR23", 33 | "NR24", 34 | "NR30", 35 | "NR31", 36 | "NR32", 37 | "NR33", 38 | "NR34", 39 | "UNDEF", 40 | /* 0x20 */ 41 | "NR41", 42 | "NR42", 43 | "NR43", 44 | "NR44", 45 | "NR50", 46 | "NR51", 47 | "NR52", 48 | "UNDEF", 49 | "UNDEF", 50 | "UNDEF", 51 | "UNDEF", 52 | "UNDEF", 53 | "UNDEF", 54 | "UNDEF", 55 | "UNDEF", 56 | "UNDEF", 57 | /* 0x30 */ 58 | "Wave Pattern", 59 | "Wave Pattern", 60 | "Wave Pattern", 61 | "Wave Pattern", 62 | "Wave Pattern", 63 | "Wave Pattern", 64 | "Wave Pattern", 65 | "Wave Pattern", 66 | "Wave Pattern", 67 | "Wave Pattern", 68 | "Wave Pattern", 69 | "Wave Pattern", 70 | "Wave Pattern", 71 | "Wave Pattern", 72 | "Wave Pattern", 73 | "Wave Pattern", 74 | /* 0x40 */ 75 | "LCDC", 76 | "STAT", 77 | "SCY", 78 | "SCX", 79 | "LY", 80 | "LYC", 81 | "DMA", 82 | "BGP", 83 | "OBP0", 84 | "OBP1", 85 | "WY", 86 | "WX", 87 | "UNDEF", 88 | "KEY1", 89 | "UNDEF", 90 | "VBK", 91 | /* 0x50 */ 92 | "UNDEF", 93 | "HDMA1", 94 | "HDMA2", 95 | "HDMA3", 96 | "HDMA4", 97 | "HDMA5", 98 | "RP", 99 | "UNDEF", 100 | "UNDEF", 101 | "UNDEF", 102 | "UNDEF", 103 | "UNDEF", 104 | "UNDEF", 105 | "UNDEF", 106 | "UNDEF", 107 | "UNDEF", 108 | /* 0x60 */ 109 | "UNDEF", 110 | "UNDEF", 111 | "UNDEF", 112 | "UNDEF", 113 | "UNDEF", 114 | "UNDEF", 115 | "UNDEF", 116 | "UNDEF", 117 | "UNDEF", 118 | "UNDEF", 119 | "OCPS/OBPI", 120 | "OCPD/OBPD", 121 | "UNDEF", 122 | "UNDEF", 123 | "UNDEF", 124 | "UNDEF", 125 | /* 0x70 */ 126 | "SVBK", 127 | "UNDEF", 128 | "UNDEF", 129 | "UNDEF", 130 | "UNDEF", 131 | "UNDEF", 132 | "UNDEF", 133 | "UNDEF", 134 | "UNDEF", 135 | "UNDEF", 136 | "UNDEF", 137 | "UNDEF", 138 | "UNDEF", 139 | "UNDEF", 140 | "UNDEF", 141 | "UNDEF", 142 | }; 143 | 144 | const char* io_name(uint8_t addr) { 145 | if (addr == 0xff) return "IE"; 146 | if (addr >= 0x80) return "HIMEM"; 147 | return IO_REGISTER_NAMES[addr]; 148 | } 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /test/mrdo-asm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | # This is unfinished script to convert Mr.Do! source code to format acceptable by rgbasm 4 | 5 | 6 | import re 7 | 8 | f = open('mrdo.asm', 'r') 9 | lines = f.readlines() 10 | f.close() 11 | 12 | m = {} 13 | defs = {} 14 | 15 | stupid_names = { 'DIV': 'DIVV', 'IF': 'IFF', 'L': 'LEFT', 'D': 'DOWN' } 16 | KEYWORDS = ['LDH', 'CPL', 'SUB', 'DI', 'RRCA', 'RES', 'STOP', 'JR', 'POP', 'EI', 'CCF', 17 | 'LD', 'DEC', 'DAA', 'RR', 'RETI', 'SCF', 'RRC', 'RRA', 'RET', 'SWAP', 'PUSH', 'BIT', 18 | 'RLCA', 'SRA', 'XOR', 'HALT', 'JP', 'SRL', 'RL', 'ADD', 'SET', 'ADC', 'CP', 'SLA', 19 | 'AND', 'RLA', 'RLC', 'SBC', 'CALL', 'RST', 'NOP', 'OR', 'INC', 'DB', 'DW', 'DS', 20 | 'HEX', 'ORG', 'END' ] 21 | 22 | wram = False 23 | for line in lines: 24 | line = re.sub(r'\s+', ' ', line.strip()) # remove whitespaces 25 | #line = re.sub(r';.*', '', line) # remove comments ; 26 | line = re.sub(r'\*.*', '', line) # remove comments * 27 | 28 | if len(line) == 0: 29 | continue 30 | 31 | # reserved variable names 32 | for name in stupid_names: 33 | if line.startswith(name + ' EQU '): 34 | line = line.replace(name + ' EQU ', stupid_names[name] + ' EQU ') 35 | elif '(' + name + ')' in line: 36 | line = line.replace('(' + name + ')', '(' +stupid_names[name] + ')') 37 | 38 | # Z80 synthax 39 | line = line.replace('DEFB ', 'DB ') 40 | line = line.replace('DEFW ', 'DW ') 41 | line = line.replace('DEFS ', 'DS ') 42 | 43 | # HEX 44 | if 'HEX ' in line: 45 | sp = line.split(' ') 46 | for i in range(0, len(sp)): 47 | if sp[i] == 'HEX': 48 | a = 'DB ' 49 | for j in range(0, (len(sp[i+1])/2) - 1): 50 | a += '$' + sp[i+1][j*2:j*2+2] + ',' 51 | a += '$' + sp[i+1][len(sp[i+1])-2:len(sp[i+1])] 52 | line = a 53 | 54 | if line.startswith('DB'): 55 | line = line.replace("D+L", "DOWN+LEFT") 56 | line = line.replace(",L", ",LEFT") 57 | line = line.replace(",D", ",LEFT") 58 | 59 | # labels 60 | first = line.split(' ')[0] 61 | if ' EQU ' in line: 62 | defs[first] = line.split(' ')[2] 63 | elif not first in KEYWORDS: 64 | line = line.replace(first, first + ':') 65 | 66 | # () to [] 67 | line = line.replace('(', '[') 68 | line = line.replace(')', ']') 69 | 70 | # wtf? 71 | if '<' in line or '>' in line: 72 | line = ';' + line + ' ; WTF?' 73 | 74 | if line.startswith('ORG WORKRAM+'): 75 | line = 'SECTION "' + line + '",BSS[' + line.replace('ORG WORKRAM+', '') + ']' 76 | wram = True 77 | elif line.startswith('ORG '): 78 | line = 'SECTION "' + line + '",HOME[' + line.split(' ')[1] + ']' 79 | wram = False 80 | if not wram: 81 | print line 82 | -------------------------------------------------------------------------------- /src/rom.h: -------------------------------------------------------------------------------- 1 | #ifndef __GB_DASM_ROM__H__ 2 | #define __GB_DASM_ROM__H__ 3 | 4 | /* rom.h: GameBoy ROM content loading. */ 5 | 6 | #include "stdinc.h" 7 | #include "header.h" 8 | 9 | typedef struct rom { 10 | char* filename; 11 | uint8_t* raw; 12 | uint32_t total; 13 | } rom; 14 | 15 | rom* rom_load(const char* filename) { 16 | rom* r; 17 | FILE* f; 18 | uint32_t total; 19 | 20 | r = NULL; 21 | 22 | /* Read total file content, shouldn't exceed 4GB ;) */ 23 | f = fopen(filename, "rb"); 24 | if(f) { 25 | fseek(f, 0, SEEK_END); 26 | total = ftell(f); 27 | if(total > 0) { 28 | r = (rom*)malloc(sizeof(rom)); 29 | r->raw = (uint8_t*)malloc(total); 30 | r->total = total; 31 | fseek(f, 0, SEEK_SET); 32 | if(fread(r->raw, 1, total, f) != total) { 33 | free(r->raw); 34 | free(r); 35 | fclose(f); 36 | return NULL; 37 | } 38 | r->filename = strdup(filename); 39 | } 40 | fclose(f); 41 | } 42 | 43 | return r; 44 | } 45 | 46 | void rom_free(rom* r) { 47 | if(r->filename) free(r->filename); 48 | if(r->raw) free(r->raw); 49 | free(r); 50 | } 51 | 52 | cart_header* rom_header(rom* r) { 53 | return (cart_header*)r->raw; 54 | } 55 | 56 | void rom_info(rom* r) { 57 | uint8_t h_checksum; 58 | cart_header* header; 59 | 60 | if(r->total <= sizeof(cart_header)) { 61 | printf("Wrong ROM size (%d)\n", r->total); 62 | return; 63 | } 64 | 65 | header = rom_header(r); 66 | printf("Title: %s\n", header->title); 67 | switch(header->cgb) { 68 | case CGB_OR_OLD: 69 | puts("CGB flag: works GameBoy and GameBoy Color"); break; 70 | case CGB_ONLY: 71 | puts("CGB flag: works only on GameBoy Color"); break; 72 | case 0x00: 73 | puts("CGB flag: Not used, old cartridge"); break; 74 | default: 75 | printf("CGB flag: 0x%.2X\n", header->cgb); 76 | } 77 | switch(header->sgb) { 78 | case NO_SGB: 79 | puts("SGB flag: SuperGameBoy not supported"); break; 80 | case SGB: 81 | puts("SGB flag: SuperGameBoy supported"); break; 82 | default: 83 | printf("SGB flag: 0x%.2X\n", header->sgb); 84 | } 85 | if(header->type < MAX_TYPE) 86 | printf("Type: %s\n", TYPES[header->type]); 87 | else 88 | printf("Type: Unknown (0x%.2X)\n", header->type); 89 | if(header->rom < MAX_ROMS_LO) 90 | printf("ROM: %s\n", ROMS_LO[header->rom]); 91 | else if(header->rom >= 0x52 && header->rom <= 0x54) 92 | printf("ROM: %s\n", ROMS_HI[header->rom-0x52]); 93 | else 94 | printf("ROM: Unknown (0x%.2X)\n", header->rom); 95 | if(header->ram < MAX_RAMS) 96 | printf("RAM: %s\n", RAMS[header->ram]); 97 | else 98 | printf("RAM: Unknown (0x%.2X)\n", header->ram); 99 | switch(header->dest) { 100 | case JAP: puts("Destination: Japanese"); break; 101 | case NON_JAP: puts("Destination: non-Japanese"); break; 102 | default: printf("Destination: Unknown (0x%.2X)\n", header->dest); 103 | } 104 | printf("Version: 0x%.2X\n", header->version); 105 | if(header->h_checksum == (h_checksum = header_checksum(header))) 106 | puts("Header checksum: OK"); 107 | else 108 | printf("Header checksum: Wrong (0x%.2X != 0x%.2X)\n", header->h_checksum, h_checksum); 109 | } 110 | 111 | #endif 112 | 113 | -------------------------------------------------------------------------------- /src/header.h: -------------------------------------------------------------------------------- 1 | #ifndef __GB_DASM_HEADER_H__ 2 | #define __GB_DASM_HEADER_H__ 3 | 4 | /* header.h: GameBoy ROM header. */ 5 | 6 | #include "stdinc.h" 7 | 8 | /** Game supports CGB functions, but works on old gameboys also. */ 9 | #define CGB_OR_OLD 0x80 10 | /** Game works on CGB only (physically the same as 80h). */ 11 | #define CGB_ONLY 0xC0 12 | /** No SGB functions (Normal Gameboy or CGB only game). */ 13 | #define NO_SGB 0x00 14 | /** Game supports SGB functions. */ 15 | #define SGB 0x03 16 | /** Destination Japanese. */ 17 | #define JAP 0x00 18 | /** Destination non-Japanese. */ 19 | #define NON_JAP 0x01 20 | 21 | #define MAX_TYPE 0x1F 22 | const char* TYPES[MAX_TYPE] = { 23 | "ROM ONLY", /* 0x00 */ 24 | "MBC1", /* 0x01 */ 25 | "MBC1+RAM", /* 0x02 */ 26 | "MBC1+RAM+BATTERY", /* 0x03 */ 27 | "Unknown", /* 0x04 */ 28 | "MBC2", /* 0x05 */ 29 | "MBC2+BATTERY", /* 0x06 */ 30 | "Unknown", /* 0x07 */ 31 | "ROM+RAM", /* 0x08 */ 32 | "ROM+RAM+BATTERY", /* 0x09 */ 33 | "Unknown", /* 0x0A */ 34 | "MMM01", /* 0x0B */ 35 | "MMM01+RAM", /* 0x0C */ 36 | "MMM01+RAM+BATTERY", /* 0x0D */ 37 | "Unknown", /* 0x0E */ 38 | "MBC3+TIMER+BATTERY", /* 0x0F */ 39 | "MBC3+TIMER+RAM+BATTERY", /* 0x10 */ 40 | "MBC3", /* 0x11 */ 41 | "MBC3+RAM", /* 0x12 */ 42 | "MBC3+RAM+BATTERY", /* 0x13 */ 43 | "Unknown", /* 0x14 */ 44 | "MBC4", /* 0x15 */ 45 | "MBC4+RAM", /* 0x16 */ 46 | "MBC4+RAM+BATTERY", /* 0x17 */ 47 | "Unknown", /* 0x18 */ 48 | "MBC5", /* 0x19 */ 49 | "MBC5+RAM", /* 0x1A */ 50 | "MBC5+RAM+BATTERY", /* 0x1B */ 51 | "MBC5+RUMBLE", /* 0x1C */ 52 | "MBC5+RUMBLE+RAM", /* 0x1D */ 53 | "MBC5+RUMBLE+RAM+BATTERY" /* 0x1E */ 54 | }; 55 | 56 | #define MAX_ROMS_LO 0x08 57 | const char* ROMS_LO[MAX_ROMS_LO] = { 58 | "32KByte", 59 | "64KByte", 60 | "128KByte", 61 | "256KByte", 62 | "512KByte", 63 | "1MByte", 64 | "2MByte", 65 | "4MByte" 66 | }; 67 | 68 | const char* ROMS_HI[3] = { 69 | "1.1MByte", 70 | "1.2MByte", 71 | "1.5MByte" 72 | }; 73 | 74 | #define MAX_RAMS 0x05 75 | const char* RAMS[MAX_RAMS] = { 76 | "None", /* 0x00 */ 77 | "2 KBytes", /* 0x01 */ 78 | "8 Kbytes", /* 0x02 */ 79 | "32 KBytes", /* 0x03 */ 80 | "128 KBytes" /* 0x04 */ 81 | }; 82 | 83 | #pragma pack(push, 1) 84 | 85 | /** Cartridge header. */ 86 | typedef struct { 87 | /* Chuj go wie. */ 88 | uint8_t hgw[0x100]; 89 | /** Entry point. */ 90 | uint8_t jmp[0x4]; 91 | /** Nintendo logo. */ 92 | uint8_t logo[0x30]; 93 | /** Title. */ 94 | uint8_t title[0xB]; 95 | /** Manufacturer code. */ 96 | uint8_t manufacturer[0x4]; 97 | /** CGB Flag. */ 98 | uint8_t cgb; 99 | /** New Licensee Code. */ 100 | uint8_t nlc[2]; 101 | /** SGB Flag. */ 102 | uint8_t sgb; 103 | /** Cartridge type. */ 104 | uint8_t type; 105 | /** ROM Size. */ 106 | uint8_t rom; 107 | /** RAM Size. */ 108 | uint8_t ram; 109 | /** Destination Code. */ 110 | uint8_t dest; 111 | /** Old Licensee Code. */ 112 | uint8_t license; 113 | /** Mask ROM Version number. */ 114 | uint8_t version; 115 | /** Header Checksum. */ 116 | uint8_t h_checksum; 117 | /** Global Checksum. */ 118 | uint8_t g_checksum[2]; 119 | } cart_header; 120 | 121 | #pragma pack(pop) 122 | 123 | uint8_t header_checksum(cart_header* header) { 124 | uint8_t cs; 125 | uint8_t* raw; 126 | int i; 127 | 128 | raw = (uint8_t*)header; 129 | cs = 0; 130 | for(i=0x134; i<=0x14C; i++) cs = cs-raw[i]-1; 131 | return cs; 132 | } 133 | 134 | #endif 135 | 136 | -------------------------------------------------------------------------------- /vs/gb-disasm.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {49FB03D9-9CC0-411F-AC16-2FF6E2BDC858} 15 | cart 16 | Win32Proj 17 | 18 | 19 | 20 | Application 21 | v140 22 | Unicode 23 | true 24 | 25 | 26 | Application 27 | v140 28 | Unicode 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | <_ProjectFileVersion>14.0.25420.1 42 | 43 | 44 | $(SolutionDir)$(Configuration)\ 45 | $(Configuration)\ 46 | true 47 | 48 | 49 | $(SolutionDir)$(Configuration)\ 50 | $(Configuration)\ 51 | false 52 | 53 | 54 | 55 | Disabled 56 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 57 | true 58 | EnableFastChecks 59 | MultiThreadedDebugDLL 60 | 61 | Level3 62 | EditAndContinue 63 | CompileAsC 64 | 65 | 66 | true 67 | Console 68 | MachineX86 69 | 70 | 71 | 72 | 73 | MaxSpeed 74 | true 75 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 76 | MultiThreaded 77 | true 78 | 79 | Level3 80 | ProgramDatabase 81 | 82 | 83 | ..\bin\$(ProjectName).exe 84 | true 85 | Console 86 | true 87 | true 88 | MachineX86 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /src/generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Generater code from opcodes from http://pastraiser.com/cpu/gameboy/gameboy_opcodes.html 3 | 4 | import re 5 | from html.parser import HTMLParser 6 | 7 | f = open('./opcodes.html', 'r') 8 | lines = f.read() 9 | f.close() 10 | 11 | class MyHTMLParser(HTMLParser): 12 | def __init__(self): 13 | HTMLParser.__init__(self) 14 | self.td = True 15 | self.last = [] 16 | self.col = 0 17 | self.out = [] 18 | 19 | def handle_starttag(self, tag, attrs): 20 | if(tag == 'td'): 21 | self.td = True 22 | self.col += 1 23 | elif(tag == 'table'): 24 | self.col = 0 25 | 26 | def handle_endtag(self, tag): 27 | if(tag == 'td'): 28 | self.td = False 29 | if(self.col > 1): 30 | self.out.append(self.last) 31 | self.last = [] 32 | elif(tag == 'tr'): 33 | self.col = 0 34 | 35 | def handle_data(self, data): 36 | if(self.td == True): 37 | # fix for some weird behaviour introduced in python3 38 | if '\xa0' in data: 39 | data = data.split('\xa0') 40 | self.last.extend(data) 41 | else: 42 | self.last.append(data) 43 | self.last = list(filter(lambda x: x != '', self.last)) 44 | 45 | parser = MyHTMLParser() 46 | parser.feed(lines) 47 | 48 | # variables 49 | VARS = ['d8', 'd16', 'a8', 'a16', 'r8'] 50 | # additional operations for specified functions, bank change emulation 51 | spec = { 52 | 0x3e: '\ta = addr8;', 53 | 0xea: '\tif(mbc != ROM_ONLY && (addr16 == 0x2000 || addr16 == 0x2100)) {\n' 54 | + '\t\tprintf("Info: Bank switch to %d at 0x%.8X\\n", bank, phy(pc));\n' 55 | + '\t\tbank = a;\n\t}', 56 | 0xe0: '\thmem[addr8] = a;', 57 | 0xf0: '\ta = hmem[addr8];', 58 | 0x76: '\tprintf("Warning: RGBASM could not handle HALT instruction properly (0x%.8X)\\n", phy(pc));' 59 | } 60 | 61 | print('/* AUTOGENERATED - look at generator.py */') 62 | for i in range(0, 0x100): 63 | op = parser.out[i+0x10] 64 | if(len(op) == 0): # not used 65 | continue 66 | elif(i == 0xCB): 67 | print('/* bit operations */') 68 | print('case 0xcb:') 69 | print('\tswitch(r->raw[phy(pc+1)]) {') 70 | for j in range(0, 0x100): 71 | op2 = parser.out[j+0x120][0] 72 | print('\t/* %s */' % op2) 73 | print('\tcase ' + hex(j) + ':') 74 | print('\t\tsops = sops_add(sops, op_0_2("%s"));' % op2) 75 | print('\t\tbreak;') 76 | print('\t}') 77 | print('\tpc += 2;') 78 | print('\tbreak;') 79 | continue 80 | elif(i == 0x10): # STOP instruction has 2 bytes but no arguments 81 | print('/* STOP */') 82 | print('case 0x10:') 83 | print('\tsops = sops_add(sops, op_0("STOP"));') 84 | print('\tpc += 2;') 85 | print('\tbreak;') 86 | continue 87 | 88 | print('/* ' + op[0] + ' */') # op[0] = operation description 89 | print('case ' + hex(i) + ':') 90 | if(op[1] == '1'): # 1-byte ops 91 | name = op[0] 92 | print('\tsops = sops_add(sops, op_0("%s"));' % name) 93 | elif(op[1] == '2'): # 2-byte ops 94 | print('\taddr8 = r->raw[phy(pc+1)];') 95 | for var in VARS: 96 | bvar = '(' + var + ')' 97 | if op[0].endswith(var): 98 | name = op[0][0:len(op[0])-len(var)] 99 | print('\tsops = sops_add(sops, op_r8("%s", addr8));' % name) 100 | break 101 | elif op[0].endswith(bvar): 102 | name = op[0][0:len(op[0])-len(bvar)] 103 | print('\tsops = sops_add(sops, op_rb8("%s", addr8));' % name) 104 | break 105 | elif bvar in op[0]: 106 | where = op[0].find(bvar) 107 | name = op[0][0:where].strip() 108 | r = op[0][where+len(bvar):].strip() 109 | print('\tsops = sops_add(sops, op_lb8("%s", addr8, "%s"));' % (name, r)) 110 | break 111 | elif var in op[0]: 112 | where = op[0].find(var) 113 | name = op[0][0:where].strip() 114 | r = op[0][where+len(var):].strip() 115 | print('\tsops = sops_add(sops, op_l8("%s", addr8, "%s"));' % (name, r)) 116 | break 117 | elif(op[1] == '3'): # 3-byte ops 118 | print('\taddr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8);') 119 | for var in VARS: 120 | bvar = '(' + var + ')' 121 | if op[0].endswith(var): 122 | name = op[0][0:len(op[0])-len(var)] 123 | print('\tsops = sops_add(sops, op_r16("%s", addr16));' % name) 124 | break 125 | elif op[0].endswith(bvar): 126 | name = op[0][0:len(op[0])-len(bvar)] 127 | print('\tsops = sops_add(sops, op_rb16("%s", addr16));' % name) 128 | break 129 | elif bvar in op[0]: 130 | where = op[0].find(bvar) 131 | name = op[0][0:where].strip() 132 | r = op[0][where+len(bvar):].strip() 133 | print('\tsops = sops_add(sops, op_lb16("%s", addr16, "%s"));' % (name, r)) 134 | break 135 | elif var in op[0]: 136 | where = op[0].find(var) 137 | name = op[0][0:where].strip() 138 | r = op[0][where+len(var):].strip() 139 | print('\tsops = sops_add(sops, op_l16("%s", addr16, "%s"));' % (name, r)) 140 | break 141 | else: 142 | print(op) 143 | raise Exception('Wrong operator length') 144 | 145 | if i in spec: 146 | print(spec[i]) 147 | 148 | # jumps/call handling 149 | name = name.strip() 150 | if i == 0xe9: # skip JP (HL) 151 | print('\tpc += ' + op[1] + ';') 152 | elif name.startswith('CALL'): # conditional jumps/calls 153 | print('\taddr_buff_add(&call_addr, phy(addr16));') 154 | print('\tif(call_follow) jmp16(addr16); else pc += ' + op[1] +';') 155 | elif name.startswith('JP '): 156 | print('\taddr_buff_add(&jmp_addr, phy(addr16));') 157 | print('\tif(jmp_follow) jmp16(addr16); else pc += ' + op[1] +';') 158 | elif name.startswith('JR '): 159 | print('\taddr_buff_add(&jmp_addr, phy(rel_addr(addr8)));') 160 | print('\tif(jmp_follow) jmp8(addr8); else pc += ' + op[1] +';') 161 | elif name.startswith('JP'): # unconditional jumps 162 | print('\taddr_buff_add(&jmp_addr, phy(addr16));') 163 | print('\tif(jmp_follow) jmpu16(addr16); else pc = start;') 164 | elif name.startswith('JR'): 165 | print('\taddr_buff_add(&jmp_addr, phy(rel_addr(addr8)));') 166 | print('\tif(jmp_follow) jmpu8(addr8); else pc = start;') 167 | elif name.startswith('RET '): # conditional ret 168 | print('\tpc += 1;') 169 | elif name.startswith('RET'): # unconditional ret 170 | print('\tret();') 171 | else: # skip any other instruction 172 | print('\tpc += ' + op[1] + ';') 173 | print('\tbreak;') 174 | 175 | print('/* AUTOGENERATED - end */') 176 | -------------------------------------------------------------------------------- /src/sops.h: -------------------------------------------------------------------------------- 1 | #ifndef __GB_DASM_SOPS_H__ 2 | #define __GB_DASM_SOPS_H__ 3 | 4 | /** sops.h: Operations sorted by address. Sorted linked list. */ 5 | 6 | #include "rom.h" 7 | 8 | /** This operation is destination of a jump instruction. */ 9 | #define OP_FLAG_JMP_ADDR 0x01 10 | /** This operation is destination of a call instruction. */ 11 | #define OP_FLAG_CALL_ADDR 0x02 12 | /** Jump/call instruction. */ 13 | #define OP_FLAG_IS_JUMP 0x04 14 | 15 | /** Operation. */ 16 | typedef struct op { 17 | /** Offset in ROM. */ 18 | uint32_t off; 19 | /** Operation name and parameters. */ 20 | char name[32]; 21 | /** Operation binary code. */ 22 | uint8_t code[3]; 23 | /** Operation binary code length in bytes, max 3. */ 24 | uint8_t len; 25 | /** Flags, used for labelling. */ 26 | uint8_t flags; 27 | /** If jump or call, physical destination address. */ 28 | uint32_t addr; 29 | /** Linked list. */ 30 | struct op* next; 31 | } op; 32 | 33 | op* op_create(uint32_t off, const uint8_t* code, uint8_t len, const char* name) { 34 | op* oper; 35 | int i; 36 | 37 | oper = (op*)malloc(sizeof(op)); 38 | oper->off = off; 39 | for(i=0; icode[i] = code[i]; 41 | oper->len = len; 42 | strcpy(oper->name, name); 43 | oper->addr = 0; 44 | oper->flags = 0; 45 | oper->next = NULL; 46 | return oper; 47 | } 48 | 49 | void sops_free(op* head) { 50 | if(head) { 51 | op* sw, *tmp = head; 52 | while(tmp) { 53 | sw = tmp; 54 | tmp = tmp->next; 55 | free(sw); 56 | } 57 | } 58 | } 59 | 60 | op* sops_add(op* head, op* oper) { 61 | op* new_op = op_create(oper->off, oper->code, oper->len, oper->name); 62 | if(head) { 63 | op* tmp, *prev; 64 | tmp = head; 65 | prev = NULL; 66 | 67 | while(tmp) { 68 | if(oper->off < tmp->off) { 69 | if(prev) { 70 | prev->next = new_op; 71 | new_op->next = tmp; 72 | return head; 73 | } else { 74 | new_op->next = head; 75 | head = new_op; 76 | return head; 77 | } 78 | } else if(oper->off == tmp->off) { 79 | return head; /* already on list */ 80 | } 81 | prev = tmp; 82 | tmp = tmp->next; 83 | } 84 | 85 | prev->next = new_op; 86 | } else 87 | head = new_op; 88 | 89 | return head; 90 | } 91 | 92 | op* sops_get(op* head, uint32_t addr) { 93 | op* tmp = head; 94 | while(tmp) { 95 | if(tmp->off == addr) return tmp; 96 | tmp = tmp->next; 97 | } 98 | return NULL; 99 | } 100 | 101 | int sops_contains(op* head, uint32_t addr) { 102 | return (sops_get(head, addr) != NULL); 103 | } 104 | 105 | void sops_set_flag(op* head, uint32_t addr, uint8_t flag) { 106 | op* tmp = head; 107 | while(tmp) { 108 | if(tmp->off == addr) { 109 | tmp->flags |= flag; 110 | return; 111 | } 112 | tmp = tmp->next; 113 | } 114 | } 115 | 116 | /** Use this after call or jump instruction. */ 117 | void sops_set_jmp(op* head, uint32_t addr, uint32_t daddr) { 118 | op* tmp = head; 119 | while(tmp) { 120 | if(tmp->off == addr) { 121 | tmp->flags |= OP_FLAG_IS_JUMP; 122 | tmp->addr = daddr; 123 | return; 124 | } 125 | tmp = tmp->next; 126 | } 127 | } 128 | 129 | /** Hex dump. */ 130 | void sops_dump(op* head, FILE* f) { 131 | op* tmp = head; 132 | while(tmp) { 133 | switch(tmp->len) { 134 | case 1: 135 | fprintf(f, "[0x%.8X] 0x%.2X %s\n", 136 | tmp->off, tmp->code[0], tmp->name); 137 | break; 138 | case 2: 139 | if(strstr(tmp->name, "JR")) { 140 | fprintf(f, "[0x%.8X] 0x%.2X 0x%.2X %s ; 0x%X\n", 141 | tmp->off, tmp->code[0], tmp->code[1], tmp->name, tmp->addr); 142 | } else { 143 | fprintf(f, "[0x%.8X] 0x%.2X 0x%.2X %s\n", 144 | tmp->off, tmp->code[0], tmp->code[1], tmp->name); 145 | } 146 | break; 147 | case 3: 148 | fprintf(f, "[0x%.8X] 0x%.2X 0x%.2X 0x%.2X %s\n", 149 | tmp->off, tmp->code[0], tmp->code[1], tmp->code[2], tmp->name); 150 | break; 151 | } 152 | 153 | tmp = tmp->next; 154 | } 155 | } 156 | 157 | /** Disassembled code. */ 158 | void sops_asm(op* head, FILE* f, rom* r) { 159 | char buff[16]; 160 | op* tmp = head; 161 | uint32_t prev = 0; 162 | 163 | fprintf(f, "SECTION \"rom0\", HOME[0]\n"); 164 | 165 | while(tmp) { 166 | /* print data */ 167 | if(tmp->off != prev) { 168 | if(prev > tmp->off) 169 | fprintf(f, "\t; Something is wrong here\n"); 170 | else { 171 | int prev_bank = prev / 0x4000; 172 | int tmp_bank = tmp->off / 0x4000; 173 | if(prev_bank == tmp_bank) 174 | fprintf(f, "\n\tINCBIN \"%s\",$%x,$%x-$%x\n", r->filename, prev, tmp->off, prev); 175 | else { 176 | fprintf(f, "\n\tINCBIN \"%s\",$%x,$%x-$%x\n\n", 177 | r->filename, prev, (prev_bank+1)*0x4000, prev); 178 | fprintf(f, "SECTION \"bank%d\",DATA,BANK[$%d]\n", 179 | tmp_bank, tmp_bank); 180 | fprintf(f, "\n\tINCBIN \"%s\",$%x,$%x-$%x\n", 181 | r->filename, (prev_bank+1)*0x4000, tmp->off, (prev_bank+1)*0x4000); 182 | } 183 | } 184 | } 185 | 186 | /* print jump or call label */ 187 | if(tmp->flags & OP_FLAG_JMP_ADDR) 188 | fprintf(f, "jmp_%x:\n", tmp->off); 189 | if(tmp->flags & OP_FLAG_CALL_ADDR) 190 | fprintf(f, "sub_%x:\n", tmp->off); 191 | 192 | /* print jump or call instruction */ 193 | if(tmp->flags & OP_FLAG_IS_JUMP) { 194 | if(strstr(tmp->name, "CALL")) 195 | fprintf(f, "\tCALL sub_%x\n", tmp->addr); 196 | else { 197 | char* sep = strstr(tmp->name, ","); 198 | if(sep) { 199 | strcpy(buff, tmp->name); 200 | buff[sep-tmp->name] = 0; 201 | if(strstr(buff, " ")) /* conditional jump */ 202 | fprintf(f, "\t%s,jmp_%x\n", buff, tmp->addr); 203 | else 204 | fprintf(f, "\t%s jmp_%x\n", buff, tmp->addr); 205 | } else { 206 | sep = strstr(tmp->name, " "); 207 | if(sep) { 208 | strcpy(buff, tmp->name); 209 | buff[sep-tmp->name] = 0; 210 | fprintf(f, "\t%s jmp_%x\n", buff, tmp->addr); 211 | } else 212 | fprintf(f, "\t%s ; Something went wrong\n", tmp->name); 213 | } 214 | } 215 | } else { 216 | fprintf(f, "\t%s\n", tmp->name); 217 | } 218 | 219 | if(strcmp(tmp->name, "RET") == 0) fprintf(f, "\n"); 220 | 221 | prev = tmp->off + tmp->len; 222 | tmp = tmp->next; 223 | } 224 | 225 | /* add anything whats left */ 226 | if(prev % 0x4000 != 0) { 227 | int prev_bank = prev / 0x4000; 228 | fprintf(f, "\n\tINCBIN \"%s\",$%x,$%x-$%x\n", r->filename, prev, (prev_bank+1)*0x4000, prev); 229 | 230 | /* fill to 32KB */ 231 | if(prev_bank == 0) { 232 | fprintf(f, "\nSECTION \"bank1\",DATA,BANK[$1]\n"); 233 | fprintf(f, "\tINCBIN \"%s\",$4000,$4000\n", r->filename); 234 | } 235 | } 236 | } 237 | 238 | #endif 239 | 240 | -------------------------------------------------------------------------------- /test/drmario.asm: -------------------------------------------------------------------------------- 1 | SECTION "ROM0", HOME[0] 2 | 3 | INCBIN "drmario.gb",$0,$100-$0 4 | NOP 5 | JP jmp_150 6 | 7 | INCBIN "drmario.gb",$104,$150-$104 8 | jmp_150: 9 | JP jmp_1e8 10 | sub_153: 11 | LD BC,$D00E 12 | LD A,[BC] 13 | AND A 14 | JR NZ,jmp_167 15 | LDH A,[$CF] 16 | CP $FE 17 | JR NZ,jmp_164 18 | LD A,$01 19 | JR jmp_165 20 | jmp_164: 21 | XOR A 22 | jmp_165: 23 | LD [BC],A 24 | RET 25 | 26 | jmp_167: 27 | LD A,[$D046] 28 | LDH [$01],A 29 | JR jmp_164 30 | 31 | INCBIN "drmario.gb",$16e,$1e8-$16e 32 | jmp_1e8: 33 | XOR A 34 | LD HL,$DFFF 35 | LD C,$10 36 | LD B,$00 37 | jmp_1f0: 38 | LD [HLD],A 39 | DEC B 40 | JR NZ,jmp_1f0 41 | DEC C 42 | JR NZ,jmp_1f0 43 | LD A,$0D 44 | DI 45 | LDH [$0F],A 46 | LDH [$FF],A 47 | XOR A 48 | LDH [$42],A 49 | LDH [$43],A 50 | LDH [$A4],A 51 | LDH [$41],A 52 | LDH [$01],A 53 | LDH [$02],A 54 | LD [$D000],A 55 | LD [$D001],A 56 | LD A,$80 57 | LDH [$40],A 58 | jmp_215: 59 | LDH A,[$44] 60 | CP $94 61 | JR NZ,jmp_215 62 | LD A,$03 63 | LDH [$40],A 64 | LD A,$E1 65 | LDH [$47],A 66 | LDH [$48],A 67 | LD A,$E5 68 | LDH [$49],A 69 | LD HL,$FF26 70 | LD A,$80 71 | LD [HLD],A 72 | LD A,$FF 73 | LD [HLD],A 74 | LD [HL],$77 75 | LD HL,$FF06 76 | LD A,$BF 77 | LD [HLI],A 78 | LD A,$04 79 | LD [HL],A 80 | LD A,$01 81 | NOP 82 | NOP 83 | NOP 84 | LD SP,$CFFF 85 | XOR A 86 | LD HL,$DFFF 87 | LD B,$00 88 | jmp_24b: 89 | LD [HLD],A 90 | DEC B 91 | JR NZ,jmp_24b 92 | LD HL,$CFFF 93 | LD C,$10 94 | LD B,$00 95 | jmp_256: 96 | LD [HLD],A 97 | DEC B 98 | JR NZ,jmp_256 99 | DEC C 100 | JR NZ,jmp_256 101 | LD HL,$9FFF 102 | LD C,$20 103 | XOR A 104 | LD B,$00 105 | jmp_265: 106 | LD [HLD],A 107 | DEC B 108 | JR NZ,jmp_265 109 | DEC C 110 | JR NZ,jmp_265 111 | LD HL,$FEFF 112 | LD B,$00 113 | jmp_271: 114 | LD [HLD],A 115 | DEC B 116 | JR NZ,jmp_271 117 | LD HL,$FFFE 118 | LD B,$80 119 | jmp_27a: 120 | LD [HLD],A 121 | DEC B 122 | JR NZ,jmp_27a 123 | LD C,$B6 124 | LD B,$0A 125 | LD HL,$2386 126 | jmp_285: 127 | LD A,[HLI] 128 | LD [C],A 129 | INC C 130 | DEC B 131 | JR NZ,jmp_285 132 | CALL sub_20a3 133 | CALL $7FF3 134 | CALL sub_20bb 135 | LD A,$0D 136 | LDH [$FF],A 137 | LD A,$80 138 | LDH [$40],A 139 | XOR A 140 | LDH [$0F],A 141 | LDH [$4A],A 142 | LDH [$4B],A 143 | LDH [$E1],A 144 | LDH [$9C],A 145 | EI 146 | jmp_2a8: 147 | DI 148 | LD A,[$C4F1] 149 | AND A 150 | JR Z,jmp_2c0 151 | LDH A,[$CC] 152 | AND A 153 | LD A,$00 154 | LDH [$CC],A 155 | JR NZ,jmp_2bc 156 | LD A,$E0 157 | JR jmp_2be 158 | jmp_2bc: 159 | LDH A,[$F2] 160 | jmp_2be: 161 | LDH [$D0],A 162 | jmp_2c0: 163 | EI 164 | CALL sub_434 165 | CALL sub_231c 166 | LD HL,$DF89 167 | LD A,[HL] 168 | AND A 169 | JR Z,jmp_2d3 170 | XOR A 171 | LD [HL],A 172 | CALL sub_3002 173 | jmp_2d3: 174 | CALL $0455 175 | LDH A,[$E4] 176 | AND A 177 | JR NZ,jmp_33a 178 | LDH A,[$B1] 179 | AND A 180 | JR Z,jmp_311 181 | LD A,[$C4F1] 182 | AND A 183 | JR Z,jmp_2f1 184 | LDH A,[$AB] 185 | AND A 186 | JR NZ,jmp_2f1 187 | CALL sub_364 188 | CALL sub_3e4 189 | jmp_2f1: 190 | LDH A,[$DE] 191 | LD [$DF8F],A 192 | AND A 193 | JR Z,jmp_305 194 | CP $01 195 | JR Z,jmp_309 196 | CP $02 197 | JR Z,jmp_30d 198 | LD A,$D8 199 | JR jmp_30f 200 | jmp_305: 201 | LD A,$BF 202 | JR jmp_30f 203 | jmp_309: 204 | LD A,$C8 205 | JR jmp_30f 206 | jmp_30d: 207 | LD A,$D0 208 | jmp_30f: 209 | LDH [$06],A 210 | jmp_311: 211 | LDH A,[$CB] 212 | CP $60 213 | JR Z,jmp_33a 214 | LDH A,[$80] 215 | AND $0F 216 | CP $0F 217 | JR NZ,jmp_33a 218 | LDH A,[$B1] 219 | AND A 220 | JP Z,jmp_1e8 221 | RST $08 222 | RST $08 223 | XOR A 224 | LDH [$CC],A 225 | LD A,$F0 226 | LDH [$01],A 227 | LD A,$81 228 | LDH [$02],A 229 | jmp_332: 230 | LDH A,[$CC] 231 | AND A 232 | JR Z,jmp_332 233 | JP jmp_1e8 234 | jmp_33a: 235 | LD HL,$FFA6 236 | LD B,$02 237 | jmp_33f: 238 | LD A,[HL] 239 | AND A 240 | JR Z,jmp_344 241 | DEC [HL] 242 | jmp_344: 243 | INC L 244 | DEC B 245 | JR NZ,jmp_33f 246 | LD HL,$FFE2 247 | INC [HL] 248 | LD HL,$FFE5 249 | INC [HL] 250 | LD HL,$FFE6 251 | INC [HL] 252 | LD HL,$FFE7 253 | INC [HL] 254 | jmp_358: 255 | NOP ; rgbasm could compile halt instruction properly 256 | LDH A,[$85] 257 | AND A 258 | JR Z,jmp_358 259 | XOR A 260 | LDH [$85],A 261 | JP jmp_2a8 262 | sub_364: 263 | LDH A,[$DC] 264 | AND A 265 | JR NZ,jmp_3a3 266 | LDH A,[$D0] 267 | CP $FD 268 | JR Z,jmp_379 269 | CP $F8 270 | JR Z,jmp_394 271 | CP $55 272 | RET NC 273 | LDH [$D3],A 274 | RET 275 | 276 | jmp_379: 277 | XOR A 278 | LDH [$D0],A 279 | LD A,$F8 280 | LDH [$F4],A 281 | LD B,$17 282 | LDH A,[$B1] 283 | AND A 284 | JR NZ,jmp_38c 285 | LD A,$01 286 | LDH [$A9],A 287 | RET 288 | 289 | jmp_38c: 290 | LD A,$10 291 | LDH [$A6],A 292 | LD A,B 293 | LDH [$E1],A 294 | RET 295 | 296 | jmp_394: 297 | LD A,$FD 298 | LDH [$F4],A 299 | LD B,$0F 300 | LDH A,[$B1] 301 | AND A 302 | JR Z,jmp_38c 303 | LD B,$17 304 | JR jmp_38c 305 | jmp_3a3: 306 | LD A,[$C0A4] 307 | AND A 308 | RET Z 309 | CP $E0 310 | RET Z 311 | LD B,A 312 | jmp_3ac: 313 | LD A,B 314 | AND $C0 315 | JR NZ,jmp_3b7 316 | SLA B 317 | SLA B 318 | JR jmp_3ac 319 | jmp_3b7: 320 | LD C,B 321 | LDH A,[$D9] 322 | LD D,A 323 | jmp_3bb: 324 | LD A,D 325 | AND $C0 326 | JR NZ,jmp_3d1 327 | jmp_3c0: 328 | LD A,C 329 | AND $C0 330 | JR Z,jmp_3de 331 | SLA C 332 | RL D 333 | SLA C 334 | RL D 335 | LD A,C 336 | AND A 337 | JR NZ,jmp_3bb 338 | jmp_3d1: 339 | LD A,D 340 | LDH [$D9],A 341 | LD [$D016],A 342 | XOR A 343 | LDH [$DC],A 344 | LD [$C0A4],A 345 | RET 346 | 347 | jmp_3de: 348 | SLA C 349 | SLA C 350 | JR jmp_3c0 351 | sub_3e4: 352 | LD DE,$D008 353 | LD HL,$FFDD 354 | LD A,[HL] 355 | CP $02 356 | JR Z,jmp_416 357 | CP $01 358 | JR Z,jmp_409 359 | LD A,[DE] 360 | AND A 361 | RET NZ 362 | LD A,[$D00E] 363 | AND A 364 | JR NZ,jmp_400 365 | LDH A,[$D1] 366 | JR jmp_403 367 | jmp_400: 368 | LD A,[$D046] 369 | jmp_403: 370 | LDH [$CF],A 371 | LD A,[DE] 372 | INC A 373 | LD [DE],A 374 | RET 375 | 376 | jmp_409: 377 | LD A,[DE] 378 | AND A 379 | RET NZ 380 | LD A,$FE 381 | LDH [$CF],A 382 | LD A,[DE] 383 | INC A 384 | LD [DE],A 385 | LD [HL],$02 386 | RET 387 | 388 | jmp_416: 389 | LD A,[DE] 390 | AND A 391 | RET NZ 392 | LDH A,[$D8] 393 | LDH [$CF],A 394 | LD [$D046],A 395 | XOR A 396 | LDH [$D8],A 397 | LD [HL],A 398 | INC A 399 | LD [DE],A 400 | LDH A,[$CB] 401 | CP $60 402 | LD A,$0B 403 | JR Z,jmp_430 404 | LD A,$08 405 | jmp_430: 406 | LD [$DFE0],A 407 | RET 408 | 409 | sub_434: 410 | LD A,[$D03A] 411 | AND A 412 | RET NZ 413 | LDH A,[$CB] 414 | CP $30 415 | RET NZ 416 | LDH A,[$CF] 417 | LDH [$01],A 418 | CALL sub_153 419 | XOR A 420 | LD [$D008],A 421 | LD A,[$C4F1] 422 | AND A 423 | JR NZ,jmp_450 424 | RST $08 425 | jmp_450: 426 | LD A,$81 427 | LDH [$02],A 428 | RET 429 | 430 | INCBIN "drmario.gb",$455,$1e40-$455 431 | sub_1e40: 432 | LD HL,$C000 433 | LD B,$A0 434 | XOR A 435 | jmp_1e46: 436 | LD [HLI],A 437 | DEC B 438 | JR NZ,jmp_1e46 439 | RET 440 | 441 | 442 | INCBIN "drmario.gb",$1e4b,$20a3-$1e4b 443 | sub_20a3: 444 | LD HL,$9BFF 445 | LD BC,$0400 446 | jmp_20a9: 447 | LD A,$FF 448 | LD [HLD],A 449 | DEC BC 450 | LD A,B 451 | OR C 452 | JR NZ,jmp_20a9 453 | RET 454 | 455 | jmp_20b2: 456 | sub_20b2: 457 | LD A,[HLI] 458 | LD [DE],A 459 | INC DE 460 | DEC BC 461 | LD A,B 462 | OR C 463 | JR NZ,jmp_20b2 464 | RET 465 | 466 | sub_20bb: 467 | LD HL,$3D9E 468 | LD DE,$8000 469 | LD BC,$17FF 470 | CALL sub_20b2 471 | RET 472 | 473 | 474 | INCBIN "drmario.gb",$20c8,$20c9-$20c8 475 | sub_20c9: 476 | LD HL,$9800 477 | LD B,$12 478 | jmp_20ce: 479 | PUSH HL 480 | LD C,$14 481 | jmp_20d1: 482 | LD A,[DE] 483 | LD [HLI],A 484 | INC DE 485 | DEC C 486 | JR NZ,jmp_20d1 487 | POP HL 488 | PUSH DE 489 | LD DE,$0020 490 | ADD HL,DE 491 | POP DE 492 | DEC B 493 | JR NZ,jmp_20ce 494 | RET 495 | 496 | 497 | INCBIN "drmario.gb",$20e2,$231c-$20e2 498 | sub_231c: 499 | LD A,$20 500 | LDH [$00],A 501 | LDH A,[$00] 502 | LDH A,[$00] 503 | LDH A,[$00] 504 | LDH A,[$00] 505 | CPL 506 | AND $0F 507 | SWAP A 508 | LD B,A 509 | LD A,$10 510 | LDH [$00],A 511 | LDH A,[$00] 512 | LDH A,[$00] 513 | LDH A,[$00] 514 | LDH A,[$00] 515 | LDH A,[$00] 516 | LDH A,[$00] 517 | LDH A,[$00] 518 | LDH A,[$00] 519 | LDH A,[$00] 520 | LDH A,[$00] 521 | CPL 522 | AND $0F 523 | OR B 524 | LD C,A 525 | LDH A,[$80] 526 | XOR C 527 | AND C 528 | LDH [$81],A 529 | LD A,C 530 | LDH [$80],A 531 | LD A,$30 532 | LDH [$00],A 533 | RET 534 | 535 | 536 | INCBIN "drmario.gb",$2359,$3002-$2359 537 | sub_3002: 538 | LDH A,[$E4] 539 | AND A 540 | JR NZ,jmp_3013 541 | LD B,$01 542 | LDH A,[$C1] 543 | AND A 544 | JR Z,jmp_3019 545 | INC B 546 | CP $01 547 | JR Z,jmp_3019 548 | jmp_3013: 549 | LD A,$07 550 | LD [$DFE8],A 551 | RET 552 | 553 | jmp_3019: 554 | LD A,B 555 | LD [$DFE8],A 556 | RET 557 | 558 | INCBIN "drmario.gb",$301E,$4000-$301E 559 | 560 | SECTION "bank1",DATA,BANK[$1] 561 | INCBIN "drmario.gb",$4000,$4000 562 | 563 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include "stdinc.h" 2 | #include "rom.h" 3 | #include "sops.h" 4 | #include "state.h" 5 | #include "addr_buff.h" 6 | #include "io.h" 7 | 8 | /* 9 | $FFFF Interrupt Enable Flag 10 | $FF80-$FFFE Zero Page - 127 bytes 11 | $FF00-$FF7F Hardware I/O Registers 12 | $FEA0-$FEFF Unusable Memory 13 | $FE00-$FE9F OAM - Object Attribute Memory 14 | $E000-$FDFF Echo RAM - Reserved, Do Not Use 15 | $D000-$DFFF Internal RAM - Bank 1-7 (switchable - CGB only) 16 | $C000-$CFFF Internal RAM - Bank 0 (fixed) 17 | $A000-$BFFF Cartridge RAM (If Available) 18 | $9C00-$9FFF BG Map Data 2 19 | $9800-$9BFF BG Map Data 1 20 | $8000-$97FF Character RAM 21 | $4000-$7FFF Cartridge ROM - Switchable Banks 1-xx 22 | $0150-$3FFF Cartridge ROM - Bank 0 (fixed) 23 | $0100-$014F Cartridge Header Area 24 | $0000-$00FF Restart and Interrupt Vectors 25 | */ 26 | 27 | 28 | /* GLOBALS - start */ 29 | 30 | /** ROM raw content. */ 31 | rom* r; 32 | 33 | /* MBC types. */ 34 | #define ROM_ONLY 0x00 35 | #define MBC1 0x01 36 | /** MBC type. */ 37 | uint8_t mbc; 38 | 39 | /** Temporary buffer for formatting. */ 40 | char tmp[128]; 41 | 42 | /** Current memory bank. */ 43 | int bank; 44 | /** Program counter. */ 45 | uint16_t pc; 46 | /** Register A. */ 47 | uint8_t a; 48 | /** 0xFF00-0xFFFF used for LDH operation. TODO: check what LDH really does */ 49 | uint8_t hmem[0xFF]; 50 | 51 | /** Operations list. */ 52 | op* sops; 53 | /** When branching, state to set back when returning. */ 54 | state* top; 55 | /** Adresses for jmps and calls, used for labelling. */ 56 | addr_buff jmp_addr; 57 | addr_buff call_addr; 58 | /** Start address. */ 59 | uint16_t start; 60 | /** End address. */ 61 | uint16_t end; 62 | 63 | /** Physical address mapping. */ 64 | uint32_t phy(uint16_t addr) { 65 | if(mbc == ROM_ONLY) return addr; 66 | /* TODO: for the moment we don't check the mbc, and threat MBC1, MBC3 and MBC5 equally */ 67 | if(addr < 0x4000) return addr; 68 | return ((bank-1) * 0x4000) + addr; 69 | } 70 | 71 | /** Relative address (to PC). */ 72 | uint16_t rel_addr(uint8_t addr) { 73 | if(addr & 0x80) 74 | return pc + (char)addr + 2; 75 | else 76 | return pc + (addr & 0x7F) + 2; 77 | } 78 | 79 | /** Conditional jump #1. */ 80 | void jmp16(uint16_t addr) { 81 | if(addr < end && phy(addr) < r->total) { 82 | sops_set_jmp(sops, phy(pc), phy(addr)); 83 | top = state_push(top, pc + 3, bank); 84 | pc = addr; 85 | } else { 86 | printf("[0x%.8X] Warning: Address too high, ignoring 0x%.4X (0x%.8X)\n", 87 | phy(pc), addr, phy(addr)); 88 | pc += 3; 89 | } 90 | } 91 | 92 | /** Conditional jump #2. */ 93 | uint16_t jmp8(uint8_t addr) { 94 | uint16_t new_pc = rel_addr(addr); 95 | if(new_pc < end) { 96 | sops_set_jmp(sops, phy(pc), phy(new_pc)); 97 | top = state_push(top, pc + 2, bank); 98 | pc = new_pc; 99 | return new_pc; 100 | } else { 101 | printf("[0x%.8X] Warning: Address too high, ignoring 0x%.4X (0x%.8X)\n", 102 | phy(pc), new_pc, phy(new_pc)); 103 | pc += 2; 104 | return start; 105 | } 106 | } 107 | 108 | /** Unconditional jump #1. */ 109 | void jmpu16(uint16_t addr) { 110 | if(addr < end && phy(addr) < r->total) { 111 | sops_set_jmp(sops, phy(pc), phy(addr)); 112 | pc = addr; 113 | } else { 114 | printf("[0x%.8X] Warning: Address too high, ignoring 0x%.4X (0x%.8X)\n", 115 | pc, addr, phy(addr)); 116 | pc = start; 117 | } 118 | } 119 | 120 | /** Unconditional jump #2. */ 121 | uint16_t jmpu8(uint8_t addr) { 122 | uint16_t new_pc = rel_addr(addr); 123 | if(new_pc < end && phy(new_pc) < r->total) { 124 | sops_set_jmp(sops, phy(pc), phy(new_pc)); 125 | pc = new_pc; 126 | return new_pc; 127 | } else { 128 | printf("[0x%.8X] Warning: Address too high, ignoring 0x%.4X (0x%.8X)\n", 129 | pc, new_pc, phy(new_pc)); 130 | pc = start; 131 | return start; 132 | } 133 | } 134 | 135 | /** Return from call or jump. */ 136 | void ret(void) { 137 | if(top) { 138 | pc = top->pc; 139 | bank = top->bank; 140 | top = state_pop(top); 141 | } else 142 | pc = start; 143 | } 144 | 145 | /** No-arg operator */ 146 | op* op_0(const char* opname) { 147 | return op_create(phy(pc), &(r->raw[phy(pc)]), 1, opname); 148 | } 149 | 150 | op* op_0_2(const char* opname) { 151 | return op_create(phy(pc), &(r->raw[phy(pc)]), 2, opname); 152 | } 153 | 154 | /* Adresses as right arg */ 155 | op* op_r16(const char* opname, uint16_t addr) { 156 | sprintf(tmp, "%s$%.4X", opname, addr); 157 | return op_create(phy(pc), &(r->raw[phy(pc)]), 3, tmp); 158 | } 159 | 160 | op* op_rb16(const char* opname, uint16_t addr) { 161 | sprintf(tmp, "%s[$%.4X]", opname, addr); 162 | return op_create(phy(pc), &(r->raw[phy(pc)]), 3, tmp); 163 | } 164 | 165 | op* op_r8(const char* opname, uint8_t addr) { 166 | sprintf(tmp, "%s$%.2X", opname, addr); 167 | return op_create(phy(pc), &(r->raw[phy(pc)]), 2, tmp); 168 | } 169 | 170 | op* op_rb8(const char* opname, uint8_t addr) { 171 | sprintf(tmp, "%s[$%.2X]", opname, addr); 172 | return op_create(phy(pc), &(r->raw[phy(pc)]), 2, tmp); 173 | } 174 | 175 | /* Adresses as left arg */ 176 | op* op_l16(const char* opname, uint16_t addr, const char* right) { 177 | sprintf(tmp, "%s$%.4X%s", opname, addr, right); 178 | return op_create(phy(pc), &(r->raw[phy(pc)]), 3, tmp); 179 | } 180 | 181 | op* op_lb16(const char* opname, uint16_t addr, const char* right) { 182 | sprintf(tmp, "%s[$%.4X]%s", opname, addr, right); 183 | return op_create(phy(pc), &(r->raw[phy(pc)]), 3, tmp); 184 | } 185 | 186 | op* op_l8(const char* opname, uint8_t addr, const char* right) { 187 | /* this function is used only by the LDH instruction */ 188 | sprintf(tmp, "%s$%.2X%s ; %s", opname, addr, right, io_name(addr)); 189 | return op_create(phy(pc), &(r->raw[phy(pc)]), 2, tmp); 190 | } 191 | 192 | op* op_lb8(const char* opname, uint8_t addr, const char* right) { 193 | sprintf(tmp, "%s[$%.2X]%s", opname, addr, right); 194 | return op_create(phy(pc), &(r->raw[phy(pc)]), 2, tmp); 195 | } 196 | 197 | void usage(const char* argv0) { 198 | printf( 199 | "Usage: %s -s -b -a -nc -nj\n" 200 | " -> obligatory, ROM file to be disassembled\n" 201 | " -s -> optional, start address (PC), default is 0x100\n" 202 | " -e -> optional, end adress (PC), default is 0x8000\n" 203 | " -b -> optional, memory bank number, default is 1\n" 204 | " -a -> optional, print assembly, default is print binary dump\n" 205 | " -nc -> optional, don't follow call instructions, default is to follow\n" 206 | " -nj -> optional, don't follow jump instructions, default is to follow\n", 207 | argv0); 208 | } 209 | 210 | /* Remember the times when you put everything in main? They are coming back! */ 211 | int main(int argc, char** argv) { 212 | uint8_t addr8; 213 | uint16_t addr16; 214 | int i; 215 | 216 | /* Params. */ 217 | int assembly = 0; 218 | int call_follow = 1; 219 | int jmp_follow = 1; 220 | 221 | /* Default values. */ 222 | bank = 1; 223 | start = 0x100; 224 | end = 0x8000; 225 | 226 | if(argc < 2) { 227 | usage(argv[0]); 228 | return -1; 229 | } 230 | 231 | /* Parameters parsing. */ 232 | if(argc > 2) { 233 | int arg = 2; 234 | while(arg < argc) { 235 | if(strcmp(argv[arg], "-a") == 0) { 236 | assembly = 1; 237 | arg++; 238 | } else if(strcmp(argv[arg], "-nc") == 0) { 239 | call_follow = 0; 240 | arg++; 241 | } else if(strcmp(argv[arg], "-nj") == 0) { 242 | jmp_follow = 0; 243 | arg++; 244 | } else if (strcmp(argv[arg], "-s") == 0) { 245 | if(arg+1 < argc) { 246 | uint32_t saddr; 247 | if(strstr(argv[arg+1], "0x")) { 248 | puts("Don't preceed start address with \"0x\""); 249 | return -5; 250 | } 251 | sscanf(argv[arg+1], "%X", &saddr); 252 | if(saddr >= 0x4000) { 253 | puts("Start address must be in range 0x0000-0x3FFF"); 254 | return -6; 255 | } 256 | start = (uint16_t) saddr; 257 | arg += 2; 258 | } else { 259 | puts("Specify the start address"); 260 | usage(argv[0]); 261 | return -4; 262 | } 263 | } else if (strcmp(argv[arg], "-e") == 0) { 264 | if(arg+1 < argc) { 265 | uint32_t eaddr; 266 | if(strstr(argv[arg+1], "0x")) { 267 | puts("Don't preceed end address with \"0x\""); 268 | return -7; 269 | } 270 | sscanf(argv[arg+1], "%X", &eaddr); 271 | if(eaddr > 0x8000) { 272 | puts("End address must be in range 0x0000-0x8000"); 273 | return -8; 274 | } 275 | end = (uint16_t) eaddr; 276 | arg += 2; 277 | } else { 278 | puts("Specify the start address"); 279 | usage(argv[0]); 280 | return -4; 281 | } 282 | } else if (strcmp(argv[arg], "-b") == 0) { 283 | if(arg+1 < argc) { 284 | sscanf(argv[arg+1], "%d", &bank); 285 | arg += 2; 286 | } else { 287 | puts("Specify the bank number"); 288 | usage(argv[0]); 289 | return -4; 290 | } 291 | } else { 292 | printf("Uknown argument %s\n", argv[arg]); 293 | usage(argv[0]); 294 | return -3; 295 | } 296 | } 297 | } 298 | 299 | /* Load ROM. */ 300 | r = rom_load(argv[1]); 301 | if(!r) { 302 | printf("Could not load ROM file %s\n", argv[1]); 303 | return -2; 304 | } 305 | 306 | if(!assembly) rom_info(r); 307 | 308 | /* Init globals. */ 309 | sops = NULL; 310 | top = NULL; 311 | addr_buff_init(&call_addr); 312 | addr_buff_init(&jmp_addr); 313 | pc = start; 314 | switch(rom_header(r)->type) { 315 | case 0x00: /* ROM ONLY */ 316 | case 0x08: /* ROM+RAM */ 317 | case 0x09: /* ROM+RAM+BATTERY */ 318 | mbc = ROM_ONLY; break; 319 | default: mbc = MBC1; /* TODO */ 320 | } 321 | 322 | /* Disassembling loop. */ 323 | while(1) { 324 | /* Limit PC. */ 325 | if(pc >= end) pc = start; 326 | 327 | /* Do not visit same instruction twice */ 328 | if(sops_contains(sops, phy(pc))) { 329 | /* Check if we have any other possible branches to follow */ 330 | if(top) { 331 | pc = top->pc; 332 | bank = top->bank; 333 | top = state_pop(top); 334 | } else 335 | goto finish; 336 | } 337 | 338 | /* big switch interpreting the operations */ 339 | switch(r->raw[phy(pc)]) { 340 | #include "generated.h" 341 | default: 342 | printf("Warning: Unknown opcode (0x%.2X) at 0x%.8X\n", r->raw[phy(pc)], phy(pc)); 343 | sops = sops_add(sops, op_0("-")); 344 | pc = start; 345 | } 346 | } 347 | 348 | finish: 349 | /* create labels for followed jumps and calls */ 350 | for(i=0; i 2 |   x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xA  xB  xC  xD  xE  xF  3 | 4 |  0x NOP
1  4
- - - -LD BC,d16
3  12
- - - -LD [BC],A
1  8
- - - -INC BC
1  8
- - - -INC B
1  4
Z 0 H -DEC B
1  4
Z 1 H -LD B,d8
2  8
- - - -RLCA
1  4
0 0 0 CLD [a16],SP
3  20
- - - -ADD HL,BC
1  8
- 0 H CLD A,[BC]
1  8
- - - -DEC BC
1  8
- - - -INC C
1  4
Z 0 H -DEC C
1  4
Z 1 H -LD C,d8
2  8
- - - -RRCA
1  4
0 0 0 C 5 |  1x STOP 0
2  4
- - - -LD DE,d16
3  12
- - - -LD [DE],A
1  8
- - - -INC DE
1  8
- - - -INC D
1  4
Z 0 H -DEC D
1  4
Z 1 H -LD D,d8
2  8
- - - -RLA
1  4
0 0 0 CJR r8
2  12
- - - -ADD HL,DE
1  8
- 0 H CLD A,[DE]
1  8
- - - -DEC DE
1  8
- - - -INC E
1  4
Z 0 H -DEC E
1  4
Z 1 H -LD E,d8
2  8
- - - -RRA
1  4
0 0 0 C 6 |  2x JR NZ,r8
2  12/8
- - - -LD HL,d16
3  12
- - - -LD [HLI],A
1  8
- - - -INC HL
1  8
- - - -INC H
1  4
Z 0 H -DEC H
1  4
Z 1 H -LD H,d8
2  8
- - - -DAA
1  4
Z - 0 CJR Z,r8
2  12/8
- - - -ADD HL,HL
1  8
- 0 H CLD A,[HLI]
1  8
- - - -DEC HL
1  8
- - - -INC L
1  4
Z 0 H -DEC L
1  4
Z 1 H -LD L,d8
2  8
- - - -CPL
1  4
- 1 1 - 7 |  3x JR NC,r8
2  12/8
- - - -LD SP,d16
3  12
- - - -LD [HLD],A
1  8
- - - -INC SP
1  8
- - - -INC [HL]
1  12
Z 0 H -DEC [HL]
1  12
Z 1 H -LD [HL],d8
2  12
- - - -SCF
1  4
- 0 0 1JR C,r8
2  12/8
- - - -ADD HL,SP
1  8
- 0 H CLD A,[HLD]
1  8
- - - -DEC SP
1  8
- - - -INC A
1  4
Z 0 H -DEC A
1  4
Z 1 H -LD A,d8
2  8
- - - -CCF
1  4
- 0 0 C 8 |  4x LD B,B
1  4
- - - -LD B,C
1  4
- - - -LD B,D
1  4
- - - -LD B,E
1  4
- - - -LD B,H
1  4
- - - -LD B,L
1  4
- - - -LD B,[HL]
1  8
- - - -LD B,A
1  4
- - - -LD C,B
1  4
- - - -LD C,C
1  4
- - - -LD C,D
1  4
- - - -LD C,E
1  4
- - - -LD C,H
1  4
- - - -LD C,L
1  4
- - - -LD C,[HL]
1  8
- - - -LD C,A
1  4
- - - - 9 |  5x LD D,B
1  4
- - - -LD D,C
1  4
- - - -LD D,D
1  4
- - - -LD D,E
1  4
- - - -LD D,H
1  4
- - - -LD D,L
1  4
- - - -LD D,[HL]
1  8
- - - -LD D,A
1  4
- - - -LD E,B
1  4
- - - -LD E,C
1  4
- - - -LD E,D
1  4
- - - -LD E,E
1  4
- - - -LD E,H
1  4
- - - -LD E,L
1  4
- - - -LD E,[HL]
1  8
- - - -LD E,A
1  4
- - - - 10 |  6x LD H,B
1  4
- - - -LD H,C
1  4
- - - -LD H,D
1  4
- - - -LD H,E
1  4
- - - -LD H,H
1  4
- - - -LD H,L
1  4
- - - -LD H,[HL]
1  8
- - - -LD H,A
1  4
- - - -LD L,B
1  4
- - - -LD L,C
1  4
- - - -LD L,D
1  4
- - - -LD L,E
1  4
- - - -LD L,H
1  4
- - - -LD L,L
1  4
- - - -LD L,[HL]
1  8
- - - -LD L,A
1  4
- - - - 11 |  7x LD [HL],B
1  8
- - - -LD [HL],C
1  8
- - - -LD [HL],D
1  8
- - - -LD [HL],E
1  8
- - - -LD [HL],H
1  8
- - - -LD [HL],L
1  8
- - - -HALT
1  4
- - - -LD [HL],A
1  8
- - - -LD A,B
1  4
- - - -LD A,C
1  4
- - - -LD A,D
1  4
- - - -LD A,E
1  4
- - - -LD A,H
1  4
- - - -LD A,L
1  4
- - - -LD A,[HL]
1  8
- - - -LD A,A
1  4
- - - - 12 |  8x ADD A,B
1  4
Z 0 H CADD A,C
1  4
Z 0 H CADD A,D
1  4
Z 0 H CADD A,E
1  4
Z 0 H CADD A,H
1  4
Z 0 H CADD A,L
1  4
Z 0 H CADD A,[HL]
1  8
Z 0 H CADD A,A
1  4
Z 0 H CADC A,B
1  4
Z 0 H CADC A,C
1  4
Z 0 H CADC A,D
1  4
Z 0 H CADC A,E
1  4
Z 0 H CADC A,H
1  4
Z 0 H CADC A,L
1  4
Z 0 H CADC A,[HL]
1  8
Z 0 H CADC A,A
1  4
Z 0 H C 13 |  9x SUB B
1  4
Z 1 H CSUB C
1  4
Z 1 H CSUB D
1  4
Z 1 H CSUB E
1  4
Z 1 H CSUB H
1  4
Z 1 H CSUB L
1  4
Z 1 H CSUB [HL]
1  8
Z 1 H CSUB A
1  4
Z 1 H CSBC A,B
1  4
Z 1 H CSBC A,C
1  4
Z 1 H CSBC A,D
1  4
Z 1 H CSBC A,E
1  4
Z 1 H CSBC A,H
1  4
Z 1 H CSBC A,L
1  4
Z 1 H CSBC A,[HL]
1  8
Z 1 H CSBC A,A
1  4
Z 1 H C 14 |  Ax AND B
1  4
Z 0 1 0AND C
1  4
Z 0 1 0AND D
1  4
Z 0 1 0AND E
1  4
Z 0 1 0AND H
1  4
Z 0 1 0AND L
1  4
Z 0 1 0AND [HL]
1  8
Z 0 1 0AND A
1  4
Z 0 1 0XOR B
1  4
Z 0 0 0XOR C
1  4
Z 0 0 0XOR D
1  4
Z 0 0 0XOR E
1  4
Z 0 0 0XOR H
1  4
Z 0 0 0XOR L
1  4
Z 0 0 0XOR [HL]
1  8
Z 0 0 0XOR A
1  4
Z 0 0 0 15 |  Bx OR B
1  4
Z 0 0 0OR C
1  4
Z 0 0 0OR D
1  4
Z 0 0 0OR E
1  4
Z 0 0 0OR H
1  4
Z 0 0 0OR L
1  4
Z 0 0 0OR [HL]
1  8
Z 0 0 0OR A
1  4
Z 0 0 0CP B
1  4
Z 1 H CCP C
1  4
Z 1 H CCP D
1  4
Z 1 H CCP E
1  4
Z 1 H CCP H
1  4
Z 1 H CCP L
1  4
Z 1 H CCP [HL]
1  8
Z 1 H CCP A
1  4
Z 1 H C 16 |  Cx RET NZ
1  20/8
- - - -POP BC
1  12
- - - -JP NZ,a16
3  16/12
- - - -JP a16
3  16
- - - -CALL NZ,a16
3  24/12
- - - -PUSH BC
1  16
- - - -ADD A,d8
2  8
Z 0 H CRST $00
1  16
- - - -RET Z
1  20/8
- - - -RET
1  16
- - - -JP Z,a16
3  16/12
- - - -PREFIX CB
2  4
- - - -CALL Z,a16
3  24/12
- - - -CALL a16
3  24
- - - -ADC A,d8
2  8
Z 0 H CRST $08
1  16
- - - - 17 |  Dx RET NC
1  20/8
- - - -POP DE
1  12
- - - -JP NC,a16
3  16/12
- - - - CALL NC,a16
3  24/12
- - - -PUSH DE
1  16
- - - -SUB d8
2  8
Z 1 H CRST $10
1  16
- - - -RET C
1  20/8
- - - -RETI
1  16
- - - -JP C,a16
3  16/12
- - - - CALL C,a16
3  24/12
- - - - SBC A,d8
2  8
Z 1 H CRST $18
1  16
- - - - 18 |  Ex LDH [a8],A
2  12
- - - -POP HL
1  12
- - - -LD [C],A
1  8
- - - -  PUSH HL
1  16
- - - -AND d8
2  8
Z 0 1 0RST $20
1  16
- - - -ADD SP,r8
2  16
0 0 H CJP [HL]
1  4
- - - -LD [a16],A
3  16
- - - -   XOR d8
2  8
Z 0 0 0RST $28
1  16
- - - - 19 |  Fx LDH A,[a8]
2  12
- - - -POP AF
1  12
Z N H CLD A,[C]
1  8
- - - -DI
1  4
- - - - PUSH AF
1  16
- - - -OR d8
2  8
Z 0 0 0RST $30
1  16
- - - -LD HL,SP+r8
2  12
0 0 H CLD SP,HL
1  8
- - - -LD A,[a16]
3  16
- - - -EI
1  4
- - - -  CP d8
2  8
Z 1 H CRST $38
1  16
- - - - 20 | 21 |

22 | 23 | Prefix CB 24 |

25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
  x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xA  xB  xC  xD  xE  xF 
 0x RLC B
2  8
Z 0 0 C
RLC C
2  8
Z 0 0 C
RLC D
2  8
Z 0 0 C
RLC E
2  8
Z 0 0 C
RLC H
2  8
Z 0 0 C
RLC L
2  8
Z 0 0 C
RLC [HL]
2  16
Z 0 0 C
RLC A
2  8
Z 0 0 C
RRC B
2  8
Z 0 0 C
RRC C
2  8
Z 0 0 C
RRC D
2  8
Z 0 0 C
RRC E
2  8
Z 0 0 C
RRC H
2  8
Z 0 0 C
RRC L
2  8
Z 0 0 C
RRC [HL]
2  16
Z 0 0 C
RRC A
2  8
Z 0 0 C
 1x RL B
2  8
Z 0 0 C
RL C
2  8
Z 0 0 C
RL D
2  8
Z 0 0 C
RL E
2  8
Z 0 0 C
RL H
2  8
Z 0 0 C
RL L
2  8
Z 0 0 C
RL [HL]
2  16
Z 0 0 C
RL A
2  8
Z 0 0 C
RR B
2  8
Z 0 0 C
RR C
2  8
Z 0 0 C
RR D
2  8
Z 0 0 C
RR E
2  8
Z 0 0 C
RR H
2  8
Z 0 0 C
RR L
2  8
Z 0 0 C
RR [HL]
2  16
Z 0 0 C
RR A
2  8
Z 0 0 C
 2x SLA B
2  8
Z 0 0 C
SLA C
2  8
Z 0 0 C
SLA D
2  8
Z 0 0 C
SLA E
2  8
Z 0 0 C
SLA H
2  8
Z 0 0 C
SLA L
2  8
Z 0 0 C
SLA [HL]
2  16
Z 0 0 C
SLA A
2  8
Z 0 0 C
SRA B
2  8
Z 0 0 0
SRA C
2  8
Z 0 0 0
SRA D
2  8
Z 0 0 0
SRA E
2  8
Z 0 0 0
SRA H
2  8
Z 0 0 0
SRA L
2  8
Z 0 0 0
SRA [HL]
2  16
Z 0 0 0
SRA A
2  8
Z 0 0 0
 3x SWAP B
2  8
Z 0 0 0
SWAP C
2  8
Z 0 0 0
SWAP D
2  8
Z 0 0 0
SWAP E
2  8
Z 0 0 0
SWAP H
2  8
Z 0 0 0
SWAP L
2  8
Z 0 0 0
SWAP [HL]
2  16
Z 0 0 0
SWAP A
2  8
Z 0 0 0
SRL B
2  8
Z 0 0 C
SRL C
2  8
Z 0 0 C
SRL D
2  8
Z 0 0 C
SRL E
2  8
Z 0 0 C
SRL H
2  8
Z 0 0 C
SRL L
2  8
Z 0 0 C
SRL [HL]
2  16
Z 0 0 C
SRL A
2  8
Z 0 0 C
 4x BIT 0,B
2  8
Z 0 1 -
BIT 0,C
2  8
Z 0 1 -
BIT 0,D
2  8
Z 0 1 -
BIT 0,E
2  8
Z 0 1 -
BIT 0,H
2  8
Z 0 1 -
BIT 0,L
2  8
Z 0 1 -
BIT 0,[HL]
2  16
Z 0 1 -
BIT 0,A
2  8
Z 0 1 -
BIT 1,B
2  8
Z 0 1 -
BIT 1,C
2  8
Z 0 1 -
BIT 1,D
2  8
Z 0 1 -
BIT 1,E
2  8
Z 0 1 -
BIT 1,H
2  8
Z 0 1 -
BIT 1,L
2  8
Z 0 1 -
BIT 1,[HL]
2  16
Z 0 1 -
BIT 1,A
2  8
Z 0 1 -
 5x BIT 2,B
2  8
Z 0 1 -
BIT 2,C
2  8
Z 0 1 -
BIT 2,D
2  8
Z 0 1 -
BIT 2,E
2  8
Z 0 1 -
BIT 2,H
2  8
Z 0 1 -
BIT 2,L
2  8
Z 0 1 -
BIT 2,[HL]
2  16
Z 0 1 -
BIT 2,A
2  8
Z 0 1 -
BIT 3,B
2  8
Z 0 1 -
BIT 3,C
2  8
Z 0 1 -
BIT 3,D
2  8
Z 0 1 -
BIT 3,E
2  8
Z 0 1 -
BIT 3,H
2  8
Z 0 1 -
BIT 3,L
2  8
Z 0 1 -
BIT 3,[HL]
2  16
Z 0 1 -
BIT 3,A
2  8
Z 0 1 -
 6x BIT 4,B
2  8
Z 0 1 -
BIT 4,C
2  8
Z 0 1 -
BIT 4,D
2  8
Z 0 1 -
BIT 4,E
2  8
Z 0 1 -
BIT 4,H
2  8
Z 0 1 -
BIT 4,L
2  8
Z 0 1 -
BIT 4,[HL]
2  16
Z 0 1 -
BIT 4,A
2  8
Z 0 1 -
BIT 5,B
2  8
Z 0 1 -
BIT 5,C
2  8
Z 0 1 -
BIT 5,D
2  8
Z 0 1 -
BIT 5,E
2  8
Z 0 1 -
BIT 5,H
2  8
Z 0 1 -
BIT 5,L
2  8
Z 0 1 -
BIT 5,[HL]
2  16
Z 0 1 -
BIT 5,A
2  8
Z 0 1 -
 7x BIT 6,B
2  8
Z 0 1 -
BIT 6,C
2  8
Z 0 1 -
BIT 6,D
2  8
Z 0 1 -
BIT 6,E
2  8
Z 0 1 -
BIT 6,H
2  8
Z 0 1 -
BIT 6,L
2  8
Z 0 1 -
BIT 6,[HL]
2  16
Z 0 1 -
BIT 6,A
2  8
Z 0 1 -
BIT 7,B
2  8
Z 0 1 -
BIT 7,C
2  8
Z 0 1 -
BIT 7,D
2  8
Z 0 1 -
BIT 7,E
2  8
Z 0 1 -
BIT 7,H
2  8
Z 0 1 -
BIT 7,L
2  8
Z 0 1 -
BIT 7,[HL]
2  16
Z 0 1 -
BIT 7,A
2  8
Z 0 1 -
 8x RES 0,B
2  8
- - - -
RES 0,C
2  8
- - - -
RES 0,D
2  8
- - - -
RES 0,E
2  8
- - - -
RES 0,H
2  8
- - - -
RES 0,L
2  8
- - - -
RES 0,[HL]
2  16
- - - -
RES 0,A
2  8
- - - -
RES 1,B
2  8
- - - -
RES 1,C
2  8
- - - -
RES 1,D
2  8
- - - -
RES 1,E
2  8
- - - -
RES 1,H
2  8
- - - -
RES 1,L
2  8
- - - -
RES 1,[HL]
2  16
- - - -
RES 1,A
2  8
- - - -
 9x RES 2,B
2  8
- - - -
RES 2,C
2  8
- - - -
RES 2,D
2  8
- - - -
RES 2,E
2  8
- - - -
RES 2,H
2  8
- - - -
RES 2,L
2  8
- - - -
RES 2,[HL]
2  16
- - - -
RES 2,A
2  8
- - - -
RES 3,B
2  8
- - - -
RES 3,C
2  8
- - - -
RES 3,D
2  8
- - - -
RES 3,E
2  8
- - - -
RES 3,H
2  8
- - - -
RES 3,L
2  8
- - - -
RES 3,[HL]
2  16
- - - -
RES 3,A
2  8
- - - -
 Ax RES 4,B
2  8
- - - -
RES 4,C
2  8
- - - -
RES 4,D
2  8
- - - -
RES 4,E
2  8
- - - -
RES 4,H
2  8
- - - -
RES 4,L
2  8
- - - -
RES 4,[HL]
2  16
- - - -
RES 4,A
2  8
- - - -
RES 5,B
2  8
- - - -
RES 5,C
2  8
- - - -
RES 5,D
2  8
- - - -
RES 5,E
2  8
- - - -
RES 5,H
2  8
- - - -
RES 5,L
2  8
- - - -
RES 5,[HL]
2  16
- - - -
RES 5,A
2  8
- - - -
 Bx RES 6,B
2  8
- - - -
RES 6,C
2  8
- - - -
RES 6,D
2  8
- - - -
RES 6,E
2  8
- - - -
RES 6,H
2  8
- - - -
RES 6,L
2  8
- - - -
RES 6,[HL]
2  16
- - - -
RES 6,A
2  8
- - - -
RES 7,B
2  8
- - - -
RES 7,C
2  8
- - - -
RES 7,D
2  8
- - - -
RES 7,E
2  8
- - - -
RES 7,H
2  8
- - - -
RES 7,L
2  8
- - - -
RES 7,[HL]
2  16
- - - -
RES 7,A
2  8
- - - -
 Cx SET 0,B
2  8
- - - -
SET 0,C
2  8
- - - -
SET 0,D
2  8
- - - -
SET 0,E
2  8
- - - -
SET 0,H
2  8
- - - -
SET 0,L
2  8
- - - -
SET 0,[HL]
2  16
- - - -
SET 0,A
2  8
- - - -
SET 1,B
2  8
- - - -
SET 1,C
2  8
- - - -
SET 1,D
2  8
- - - -
SET 1,E
2  8
- - - -
SET 1,H
2  8
- - - -
SET 1,L
2  8
- - - -
SET 1,[HL]
2  16
- - - -
SET 1,A
2  8
- - - -
 Dx SET 2,B
2  8
- - - -
SET 2,C
2  8
- - - -
SET 2,D
2  8
- - - -
SET 2,E
2  8
- - - -
SET 2,H
2  8
- - - -
SET 2,L
2  8
- - - -
SET 2,[HL]
2  16
- - - -
SET 2,A
2  8
- - - -
SET 3,B
2  8
- - - -
SET 3,C
2  8
- - - -
SET 3,D
2  8
- - - -
SET 3,E
2  8
- - - -
SET 3,H
2  8
- - - -
SET 3,L
2  8
- - - -
SET 3,[HL]
2  16
- - - -
SET 3,A
2  8
- - - -
 Ex SET 4,B
2  8
- - - -
SET 4,C
2  8
- - - -
SET 4,D
2  8
- - - -
SET 4,E
2  8
- - - -
SET 4,H
2  8
- - - -
SET 4,L
2  8
- - - -
SET 4,[HL]
2  16
- - - -
SET 4,A
2  8
- - - -
SET 5,B
2  8
- - - -
SET 5,C
2  8
- - - -
SET 5,D
2  8
- - - -
SET 5,E
2  8
- - - -
SET 5,H
2  8
- - - -
SET 5,L
2  8
- - - -
SET 5,[HL]
2  16
- - - -
SET 5,A
2  8
- - - -
 Fx SET 6,B
2  8
- - - -
SET 6,C
2  8
- - - -
SET 6,D
2  8
- - - -
SET 6,E
2  8
- - - -
SET 6,H
2  8
- - - -
SET 6,L
2  8
- - - -
SET 6,[HL]
2  16
- - - -
SET 6,A
2  8
- - - -
SET 7,B
2  8
- - - -
SET 7,C
2  8
- - - -
SET 7,D
2  8
- - - -
SET 7,E
2  8
- - - -
SET 7,H
2  8
- - - -
SET 7,L
2  8
- - - -
SET 7,[HL]
2  16
- - - -
SET 7,A
2  8
- - - -
46 | -------------------------------------------------------------------------------- /src/generated.h: -------------------------------------------------------------------------------- 1 | /* AUTOGENERATED - look at generator.py */ 2 | /* NOP */ 3 | case 0x0: 4 | sops = sops_add(sops, op_0("NOP")); 5 | pc += 1; 6 | break; 7 | /* LD BC,d16 */ 8 | case 0x1: 9 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 10 | sops = sops_add(sops, op_r16("LD BC,", addr16)); 11 | pc += 3; 12 | break; 13 | /* LD [BC],A */ 14 | case 0x2: 15 | sops = sops_add(sops, op_0("LD [BC],A")); 16 | pc += 1; 17 | break; 18 | /* INC BC */ 19 | case 0x3: 20 | sops = sops_add(sops, op_0("INC BC")); 21 | pc += 1; 22 | break; 23 | /* INC B */ 24 | case 0x4: 25 | sops = sops_add(sops, op_0("INC B")); 26 | pc += 1; 27 | break; 28 | /* DEC B */ 29 | case 0x5: 30 | sops = sops_add(sops, op_0("DEC B")); 31 | pc += 1; 32 | break; 33 | /* LD B,d8 */ 34 | case 0x6: 35 | addr8 = r->raw[phy(pc+1)]; 36 | sops = sops_add(sops, op_r8("LD B,", addr8)); 37 | pc += 2; 38 | break; 39 | /* RLCA */ 40 | case 0x7: 41 | sops = sops_add(sops, op_0("RLCA")); 42 | pc += 1; 43 | break; 44 | /* LD [a16],SP */ 45 | case 0x8: 46 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 47 | sops = sops_add(sops, op_l16("LD [", addr16, "],SP")); 48 | pc += 3; 49 | break; 50 | /* ADD HL,BC */ 51 | case 0x9: 52 | sops = sops_add(sops, op_0("ADD HL,BC")); 53 | pc += 1; 54 | break; 55 | /* LD A,[BC] */ 56 | case 0xa: 57 | sops = sops_add(sops, op_0("LD A,[BC]")); 58 | pc += 1; 59 | break; 60 | /* DEC BC */ 61 | case 0xb: 62 | sops = sops_add(sops, op_0("DEC BC")); 63 | pc += 1; 64 | break; 65 | /* INC C */ 66 | case 0xc: 67 | sops = sops_add(sops, op_0("INC C")); 68 | pc += 1; 69 | break; 70 | /* DEC C */ 71 | case 0xd: 72 | sops = sops_add(sops, op_0("DEC C")); 73 | pc += 1; 74 | break; 75 | /* LD C,d8 */ 76 | case 0xe: 77 | addr8 = r->raw[phy(pc+1)]; 78 | sops = sops_add(sops, op_r8("LD C,", addr8)); 79 | pc += 2; 80 | break; 81 | /* RRCA */ 82 | case 0xf: 83 | sops = sops_add(sops, op_0("RRCA")); 84 | pc += 1; 85 | break; 86 | /* STOP */ 87 | case 0x10: 88 | sops = sops_add(sops, op_0("STOP")); 89 | pc += 2; 90 | break; 91 | /* LD DE,d16 */ 92 | case 0x11: 93 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 94 | sops = sops_add(sops, op_r16("LD DE,", addr16)); 95 | pc += 3; 96 | break; 97 | /* LD [DE],A */ 98 | case 0x12: 99 | sops = sops_add(sops, op_0("LD [DE],A")); 100 | pc += 1; 101 | break; 102 | /* INC DE */ 103 | case 0x13: 104 | sops = sops_add(sops, op_0("INC DE")); 105 | pc += 1; 106 | break; 107 | /* INC D */ 108 | case 0x14: 109 | sops = sops_add(sops, op_0("INC D")); 110 | pc += 1; 111 | break; 112 | /* DEC D */ 113 | case 0x15: 114 | sops = sops_add(sops, op_0("DEC D")); 115 | pc += 1; 116 | break; 117 | /* LD D,d8 */ 118 | case 0x16: 119 | addr8 = r->raw[phy(pc+1)]; 120 | sops = sops_add(sops, op_r8("LD D,", addr8)); 121 | pc += 2; 122 | break; 123 | /* RLA */ 124 | case 0x17: 125 | sops = sops_add(sops, op_0("RLA")); 126 | pc += 1; 127 | break; 128 | /* JR r8 */ 129 | case 0x18: 130 | addr8 = r->raw[phy(pc+1)]; 131 | sops = sops_add(sops, op_r8("JR ", addr8)); 132 | addr_buff_add(&jmp_addr, phy(rel_addr(addr8))); 133 | if(jmp_follow) jmpu8(addr8); else pc = start; 134 | break; 135 | /* ADD HL,DE */ 136 | case 0x19: 137 | sops = sops_add(sops, op_0("ADD HL,DE")); 138 | pc += 1; 139 | break; 140 | /* LD A,[DE] */ 141 | case 0x1a: 142 | sops = sops_add(sops, op_0("LD A,[DE]")); 143 | pc += 1; 144 | break; 145 | /* DEC DE */ 146 | case 0x1b: 147 | sops = sops_add(sops, op_0("DEC DE")); 148 | pc += 1; 149 | break; 150 | /* INC E */ 151 | case 0x1c: 152 | sops = sops_add(sops, op_0("INC E")); 153 | pc += 1; 154 | break; 155 | /* DEC E */ 156 | case 0x1d: 157 | sops = sops_add(sops, op_0("DEC E")); 158 | pc += 1; 159 | break; 160 | /* LD E,d8 */ 161 | case 0x1e: 162 | addr8 = r->raw[phy(pc+1)]; 163 | sops = sops_add(sops, op_r8("LD E,", addr8)); 164 | pc += 2; 165 | break; 166 | /* RRA */ 167 | case 0x1f: 168 | sops = sops_add(sops, op_0("RRA")); 169 | pc += 1; 170 | break; 171 | /* JR NZ,r8 */ 172 | case 0x20: 173 | addr8 = r->raw[phy(pc+1)]; 174 | sops = sops_add(sops, op_r8("JR NZ,", addr8)); 175 | addr_buff_add(&jmp_addr, phy(rel_addr(addr8))); 176 | if(jmp_follow) jmp8(addr8); else pc += 2; 177 | break; 178 | /* LD HL,d16 */ 179 | case 0x21: 180 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 181 | sops = sops_add(sops, op_r16("LD HL,", addr16)); 182 | pc += 3; 183 | break; 184 | /* LD [HLI],A */ 185 | case 0x22: 186 | sops = sops_add(sops, op_0("LD [HLI],A")); 187 | pc += 1; 188 | break; 189 | /* INC HL */ 190 | case 0x23: 191 | sops = sops_add(sops, op_0("INC HL")); 192 | pc += 1; 193 | break; 194 | /* INC H */ 195 | case 0x24: 196 | sops = sops_add(sops, op_0("INC H")); 197 | pc += 1; 198 | break; 199 | /* DEC H */ 200 | case 0x25: 201 | sops = sops_add(sops, op_0("DEC H")); 202 | pc += 1; 203 | break; 204 | /* LD H,d8 */ 205 | case 0x26: 206 | addr8 = r->raw[phy(pc+1)]; 207 | sops = sops_add(sops, op_r8("LD H,", addr8)); 208 | pc += 2; 209 | break; 210 | /* DAA */ 211 | case 0x27: 212 | sops = sops_add(sops, op_0("DAA")); 213 | pc += 1; 214 | break; 215 | /* JR Z,r8 */ 216 | case 0x28: 217 | addr8 = r->raw[phy(pc+1)]; 218 | sops = sops_add(sops, op_r8("JR Z,", addr8)); 219 | addr_buff_add(&jmp_addr, phy(rel_addr(addr8))); 220 | if(jmp_follow) jmp8(addr8); else pc += 2; 221 | break; 222 | /* ADD HL,HL */ 223 | case 0x29: 224 | sops = sops_add(sops, op_0("ADD HL,HL")); 225 | pc += 1; 226 | break; 227 | /* LD A,[HLI] */ 228 | case 0x2a: 229 | sops = sops_add(sops, op_0("LD A,[HLI]")); 230 | pc += 1; 231 | break; 232 | /* DEC HL */ 233 | case 0x2b: 234 | sops = sops_add(sops, op_0("DEC HL")); 235 | pc += 1; 236 | break; 237 | /* INC L */ 238 | case 0x2c: 239 | sops = sops_add(sops, op_0("INC L")); 240 | pc += 1; 241 | break; 242 | /* DEC L */ 243 | case 0x2d: 244 | sops = sops_add(sops, op_0("DEC L")); 245 | pc += 1; 246 | break; 247 | /* LD L,d8 */ 248 | case 0x2e: 249 | addr8 = r->raw[phy(pc+1)]; 250 | sops = sops_add(sops, op_r8("LD L,", addr8)); 251 | pc += 2; 252 | break; 253 | /* CPL */ 254 | case 0x2f: 255 | sops = sops_add(sops, op_0("CPL")); 256 | pc += 1; 257 | break; 258 | /* JR NC,r8 */ 259 | case 0x30: 260 | addr8 = r->raw[phy(pc+1)]; 261 | sops = sops_add(sops, op_r8("JR NC,", addr8)); 262 | addr_buff_add(&jmp_addr, phy(rel_addr(addr8))); 263 | if(jmp_follow) jmp8(addr8); else pc += 2; 264 | break; 265 | /* LD SP,d16 */ 266 | case 0x31: 267 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 268 | sops = sops_add(sops, op_r16("LD SP,", addr16)); 269 | pc += 3; 270 | break; 271 | /* LD [HLD],A */ 272 | case 0x32: 273 | sops = sops_add(sops, op_0("LD [HLD],A")); 274 | pc += 1; 275 | break; 276 | /* INC SP */ 277 | case 0x33: 278 | sops = sops_add(sops, op_0("INC SP")); 279 | pc += 1; 280 | break; 281 | /* INC [HL] */ 282 | case 0x34: 283 | sops = sops_add(sops, op_0("INC [HL]")); 284 | pc += 1; 285 | break; 286 | /* DEC [HL] */ 287 | case 0x35: 288 | sops = sops_add(sops, op_0("DEC [HL]")); 289 | pc += 1; 290 | break; 291 | /* LD [HL],d8 */ 292 | case 0x36: 293 | addr8 = r->raw[phy(pc+1)]; 294 | sops = sops_add(sops, op_r8("LD [HL],", addr8)); 295 | pc += 2; 296 | break; 297 | /* SCF */ 298 | case 0x37: 299 | sops = sops_add(sops, op_0("SCF")); 300 | pc += 1; 301 | break; 302 | /* JR C,r8 */ 303 | case 0x38: 304 | addr8 = r->raw[phy(pc+1)]; 305 | sops = sops_add(sops, op_r8("JR C,", addr8)); 306 | addr_buff_add(&jmp_addr, phy(rel_addr(addr8))); 307 | if(jmp_follow) jmp8(addr8); else pc += 2; 308 | break; 309 | /* ADD HL,SP */ 310 | case 0x39: 311 | sops = sops_add(sops, op_0("ADD HL,SP")); 312 | pc += 1; 313 | break; 314 | /* LD A,[HLD] */ 315 | case 0x3a: 316 | sops = sops_add(sops, op_0("LD A,[HLD]")); 317 | pc += 1; 318 | break; 319 | /* DEC SP */ 320 | case 0x3b: 321 | sops = sops_add(sops, op_0("DEC SP")); 322 | pc += 1; 323 | break; 324 | /* INC A */ 325 | case 0x3c: 326 | sops = sops_add(sops, op_0("INC A")); 327 | pc += 1; 328 | break; 329 | /* DEC A */ 330 | case 0x3d: 331 | sops = sops_add(sops, op_0("DEC A")); 332 | pc += 1; 333 | break; 334 | /* LD A,d8 */ 335 | case 0x3e: 336 | addr8 = r->raw[phy(pc+1)]; 337 | sops = sops_add(sops, op_r8("LD A,", addr8)); 338 | a = addr8; 339 | pc += 2; 340 | break; 341 | /* CCF */ 342 | case 0x3f: 343 | sops = sops_add(sops, op_0("CCF")); 344 | pc += 1; 345 | break; 346 | /* LD B,B */ 347 | case 0x40: 348 | sops = sops_add(sops, op_0("LD B,B")); 349 | pc += 1; 350 | break; 351 | /* LD B,C */ 352 | case 0x41: 353 | sops = sops_add(sops, op_0("LD B,C")); 354 | pc += 1; 355 | break; 356 | /* LD B,D */ 357 | case 0x42: 358 | sops = sops_add(sops, op_0("LD B,D")); 359 | pc += 1; 360 | break; 361 | /* LD B,E */ 362 | case 0x43: 363 | sops = sops_add(sops, op_0("LD B,E")); 364 | pc += 1; 365 | break; 366 | /* LD B,H */ 367 | case 0x44: 368 | sops = sops_add(sops, op_0("LD B,H")); 369 | pc += 1; 370 | break; 371 | /* LD B,L */ 372 | case 0x45: 373 | sops = sops_add(sops, op_0("LD B,L")); 374 | pc += 1; 375 | break; 376 | /* LD B,[HL] */ 377 | case 0x46: 378 | sops = sops_add(sops, op_0("LD B,[HL]")); 379 | pc += 1; 380 | break; 381 | /* LD B,A */ 382 | case 0x47: 383 | sops = sops_add(sops, op_0("LD B,A")); 384 | pc += 1; 385 | break; 386 | /* LD C,B */ 387 | case 0x48: 388 | sops = sops_add(sops, op_0("LD C,B")); 389 | pc += 1; 390 | break; 391 | /* LD C,C */ 392 | case 0x49: 393 | sops = sops_add(sops, op_0("LD C,C")); 394 | pc += 1; 395 | break; 396 | /* LD C,D */ 397 | case 0x4a: 398 | sops = sops_add(sops, op_0("LD C,D")); 399 | pc += 1; 400 | break; 401 | /* LD C,E */ 402 | case 0x4b: 403 | sops = sops_add(sops, op_0("LD C,E")); 404 | pc += 1; 405 | break; 406 | /* LD C,H */ 407 | case 0x4c: 408 | sops = sops_add(sops, op_0("LD C,H")); 409 | pc += 1; 410 | break; 411 | /* LD C,L */ 412 | case 0x4d: 413 | sops = sops_add(sops, op_0("LD C,L")); 414 | pc += 1; 415 | break; 416 | /* LD C,[HL] */ 417 | case 0x4e: 418 | sops = sops_add(sops, op_0("LD C,[HL]")); 419 | pc += 1; 420 | break; 421 | /* LD C,A */ 422 | case 0x4f: 423 | sops = sops_add(sops, op_0("LD C,A")); 424 | pc += 1; 425 | break; 426 | /* LD D,B */ 427 | case 0x50: 428 | sops = sops_add(sops, op_0("LD D,B")); 429 | pc += 1; 430 | break; 431 | /* LD D,C */ 432 | case 0x51: 433 | sops = sops_add(sops, op_0("LD D,C")); 434 | pc += 1; 435 | break; 436 | /* LD D,D */ 437 | case 0x52: 438 | sops = sops_add(sops, op_0("LD D,D")); 439 | pc += 1; 440 | break; 441 | /* LD D,E */ 442 | case 0x53: 443 | sops = sops_add(sops, op_0("LD D,E")); 444 | pc += 1; 445 | break; 446 | /* LD D,H */ 447 | case 0x54: 448 | sops = sops_add(sops, op_0("LD D,H")); 449 | pc += 1; 450 | break; 451 | /* LD D,L */ 452 | case 0x55: 453 | sops = sops_add(sops, op_0("LD D,L")); 454 | pc += 1; 455 | break; 456 | /* LD D,[HL] */ 457 | case 0x56: 458 | sops = sops_add(sops, op_0("LD D,[HL]")); 459 | pc += 1; 460 | break; 461 | /* LD D,A */ 462 | case 0x57: 463 | sops = sops_add(sops, op_0("LD D,A")); 464 | pc += 1; 465 | break; 466 | /* LD E,B */ 467 | case 0x58: 468 | sops = sops_add(sops, op_0("LD E,B")); 469 | pc += 1; 470 | break; 471 | /* LD E,C */ 472 | case 0x59: 473 | sops = sops_add(sops, op_0("LD E,C")); 474 | pc += 1; 475 | break; 476 | /* LD E,D */ 477 | case 0x5a: 478 | sops = sops_add(sops, op_0("LD E,D")); 479 | pc += 1; 480 | break; 481 | /* LD E,E */ 482 | case 0x5b: 483 | sops = sops_add(sops, op_0("LD E,E")); 484 | pc += 1; 485 | break; 486 | /* LD E,H */ 487 | case 0x5c: 488 | sops = sops_add(sops, op_0("LD E,H")); 489 | pc += 1; 490 | break; 491 | /* LD E,L */ 492 | case 0x5d: 493 | sops = sops_add(sops, op_0("LD E,L")); 494 | pc += 1; 495 | break; 496 | /* LD E,[HL] */ 497 | case 0x5e: 498 | sops = sops_add(sops, op_0("LD E,[HL]")); 499 | pc += 1; 500 | break; 501 | /* LD E,A */ 502 | case 0x5f: 503 | sops = sops_add(sops, op_0("LD E,A")); 504 | pc += 1; 505 | break; 506 | /* LD H,B */ 507 | case 0x60: 508 | sops = sops_add(sops, op_0("LD H,B")); 509 | pc += 1; 510 | break; 511 | /* LD H,C */ 512 | case 0x61: 513 | sops = sops_add(sops, op_0("LD H,C")); 514 | pc += 1; 515 | break; 516 | /* LD H,D */ 517 | case 0x62: 518 | sops = sops_add(sops, op_0("LD H,D")); 519 | pc += 1; 520 | break; 521 | /* LD H,E */ 522 | case 0x63: 523 | sops = sops_add(sops, op_0("LD H,E")); 524 | pc += 1; 525 | break; 526 | /* LD H,H */ 527 | case 0x64: 528 | sops = sops_add(sops, op_0("LD H,H")); 529 | pc += 1; 530 | break; 531 | /* LD H,L */ 532 | case 0x65: 533 | sops = sops_add(sops, op_0("LD H,L")); 534 | pc += 1; 535 | break; 536 | /* LD H,[HL] */ 537 | case 0x66: 538 | sops = sops_add(sops, op_0("LD H,[HL]")); 539 | pc += 1; 540 | break; 541 | /* LD H,A */ 542 | case 0x67: 543 | sops = sops_add(sops, op_0("LD H,A")); 544 | pc += 1; 545 | break; 546 | /* LD L,B */ 547 | case 0x68: 548 | sops = sops_add(sops, op_0("LD L,B")); 549 | pc += 1; 550 | break; 551 | /* LD L,C */ 552 | case 0x69: 553 | sops = sops_add(sops, op_0("LD L,C")); 554 | pc += 1; 555 | break; 556 | /* LD L,D */ 557 | case 0x6a: 558 | sops = sops_add(sops, op_0("LD L,D")); 559 | pc += 1; 560 | break; 561 | /* LD L,E */ 562 | case 0x6b: 563 | sops = sops_add(sops, op_0("LD L,E")); 564 | pc += 1; 565 | break; 566 | /* LD L,H */ 567 | case 0x6c: 568 | sops = sops_add(sops, op_0("LD L,H")); 569 | pc += 1; 570 | break; 571 | /* LD L,L */ 572 | case 0x6d: 573 | sops = sops_add(sops, op_0("LD L,L")); 574 | pc += 1; 575 | break; 576 | /* LD L,[HL] */ 577 | case 0x6e: 578 | sops = sops_add(sops, op_0("LD L,[HL]")); 579 | pc += 1; 580 | break; 581 | /* LD L,A */ 582 | case 0x6f: 583 | sops = sops_add(sops, op_0("LD L,A")); 584 | pc += 1; 585 | break; 586 | /* LD [HL],B */ 587 | case 0x70: 588 | sops = sops_add(sops, op_0("LD [HL],B")); 589 | pc += 1; 590 | break; 591 | /* LD [HL],C */ 592 | case 0x71: 593 | sops = sops_add(sops, op_0("LD [HL],C")); 594 | pc += 1; 595 | break; 596 | /* LD [HL],D */ 597 | case 0x72: 598 | sops = sops_add(sops, op_0("LD [HL],D")); 599 | pc += 1; 600 | break; 601 | /* LD [HL],E */ 602 | case 0x73: 603 | sops = sops_add(sops, op_0("LD [HL],E")); 604 | pc += 1; 605 | break; 606 | /* LD [HL],H */ 607 | case 0x74: 608 | sops = sops_add(sops, op_0("LD [HL],H")); 609 | pc += 1; 610 | break; 611 | /* LD [HL],L */ 612 | case 0x75: 613 | sops = sops_add(sops, op_0("LD [HL],L")); 614 | pc += 1; 615 | break; 616 | /* HALT */ 617 | case 0x76: 618 | sops = sops_add(sops, op_0("HALT")); 619 | printf("Warning: RGBASM could not handle HALT instruction properly (0x%.8X)\n", phy(pc)); 620 | pc += 1; 621 | break; 622 | /* LD [HL],A */ 623 | case 0x77: 624 | sops = sops_add(sops, op_0("LD [HL],A")); 625 | pc += 1; 626 | break; 627 | /* LD A,B */ 628 | case 0x78: 629 | sops = sops_add(sops, op_0("LD A,B")); 630 | pc += 1; 631 | break; 632 | /* LD A,C */ 633 | case 0x79: 634 | sops = sops_add(sops, op_0("LD A,C")); 635 | pc += 1; 636 | break; 637 | /* LD A,D */ 638 | case 0x7a: 639 | sops = sops_add(sops, op_0("LD A,D")); 640 | pc += 1; 641 | break; 642 | /* LD A,E */ 643 | case 0x7b: 644 | sops = sops_add(sops, op_0("LD A,E")); 645 | pc += 1; 646 | break; 647 | /* LD A,H */ 648 | case 0x7c: 649 | sops = sops_add(sops, op_0("LD A,H")); 650 | pc += 1; 651 | break; 652 | /* LD A,L */ 653 | case 0x7d: 654 | sops = sops_add(sops, op_0("LD A,L")); 655 | pc += 1; 656 | break; 657 | /* LD A,[HL] */ 658 | case 0x7e: 659 | sops = sops_add(sops, op_0("LD A,[HL]")); 660 | pc += 1; 661 | break; 662 | /* LD A,A */ 663 | case 0x7f: 664 | sops = sops_add(sops, op_0("LD A,A")); 665 | pc += 1; 666 | break; 667 | /* ADD A,B */ 668 | case 0x80: 669 | sops = sops_add(sops, op_0("ADD A,B")); 670 | pc += 1; 671 | break; 672 | /* ADD A,C */ 673 | case 0x81: 674 | sops = sops_add(sops, op_0("ADD A,C")); 675 | pc += 1; 676 | break; 677 | /* ADD A,D */ 678 | case 0x82: 679 | sops = sops_add(sops, op_0("ADD A,D")); 680 | pc += 1; 681 | break; 682 | /* ADD A,E */ 683 | case 0x83: 684 | sops = sops_add(sops, op_0("ADD A,E")); 685 | pc += 1; 686 | break; 687 | /* ADD A,H */ 688 | case 0x84: 689 | sops = sops_add(sops, op_0("ADD A,H")); 690 | pc += 1; 691 | break; 692 | /* ADD A,L */ 693 | case 0x85: 694 | sops = sops_add(sops, op_0("ADD A,L")); 695 | pc += 1; 696 | break; 697 | /* ADD A,[HL] */ 698 | case 0x86: 699 | sops = sops_add(sops, op_0("ADD A,[HL]")); 700 | pc += 1; 701 | break; 702 | /* ADD A,A */ 703 | case 0x87: 704 | sops = sops_add(sops, op_0("ADD A,A")); 705 | pc += 1; 706 | break; 707 | /* ADC A,B */ 708 | case 0x88: 709 | sops = sops_add(sops, op_0("ADC A,B")); 710 | pc += 1; 711 | break; 712 | /* ADC A,C */ 713 | case 0x89: 714 | sops = sops_add(sops, op_0("ADC A,C")); 715 | pc += 1; 716 | break; 717 | /* ADC A,D */ 718 | case 0x8a: 719 | sops = sops_add(sops, op_0("ADC A,D")); 720 | pc += 1; 721 | break; 722 | /* ADC A,E */ 723 | case 0x8b: 724 | sops = sops_add(sops, op_0("ADC A,E")); 725 | pc += 1; 726 | break; 727 | /* ADC A,H */ 728 | case 0x8c: 729 | sops = sops_add(sops, op_0("ADC A,H")); 730 | pc += 1; 731 | break; 732 | /* ADC A,L */ 733 | case 0x8d: 734 | sops = sops_add(sops, op_0("ADC A,L")); 735 | pc += 1; 736 | break; 737 | /* ADC A,[HL] */ 738 | case 0x8e: 739 | sops = sops_add(sops, op_0("ADC A,[HL]")); 740 | pc += 1; 741 | break; 742 | /* ADC A,A */ 743 | case 0x8f: 744 | sops = sops_add(sops, op_0("ADC A,A")); 745 | pc += 1; 746 | break; 747 | /* SUB B */ 748 | case 0x90: 749 | sops = sops_add(sops, op_0("SUB B")); 750 | pc += 1; 751 | break; 752 | /* SUB C */ 753 | case 0x91: 754 | sops = sops_add(sops, op_0("SUB C")); 755 | pc += 1; 756 | break; 757 | /* SUB D */ 758 | case 0x92: 759 | sops = sops_add(sops, op_0("SUB D")); 760 | pc += 1; 761 | break; 762 | /* SUB E */ 763 | case 0x93: 764 | sops = sops_add(sops, op_0("SUB E")); 765 | pc += 1; 766 | break; 767 | /* SUB H */ 768 | case 0x94: 769 | sops = sops_add(sops, op_0("SUB H")); 770 | pc += 1; 771 | break; 772 | /* SUB L */ 773 | case 0x95: 774 | sops = sops_add(sops, op_0("SUB L")); 775 | pc += 1; 776 | break; 777 | /* SUB [HL] */ 778 | case 0x96: 779 | sops = sops_add(sops, op_0("SUB [HL]")); 780 | pc += 1; 781 | break; 782 | /* SUB A */ 783 | case 0x97: 784 | sops = sops_add(sops, op_0("SUB A")); 785 | pc += 1; 786 | break; 787 | /* SBC A,B */ 788 | case 0x98: 789 | sops = sops_add(sops, op_0("SBC A,B")); 790 | pc += 1; 791 | break; 792 | /* SBC A,C */ 793 | case 0x99: 794 | sops = sops_add(sops, op_0("SBC A,C")); 795 | pc += 1; 796 | break; 797 | /* SBC A,D */ 798 | case 0x9a: 799 | sops = sops_add(sops, op_0("SBC A,D")); 800 | pc += 1; 801 | break; 802 | /* SBC A,E */ 803 | case 0x9b: 804 | sops = sops_add(sops, op_0("SBC A,E")); 805 | pc += 1; 806 | break; 807 | /* SBC A,H */ 808 | case 0x9c: 809 | sops = sops_add(sops, op_0("SBC A,H")); 810 | pc += 1; 811 | break; 812 | /* SBC A,L */ 813 | case 0x9d: 814 | sops = sops_add(sops, op_0("SBC A,L")); 815 | pc += 1; 816 | break; 817 | /* SBC A,[HL] */ 818 | case 0x9e: 819 | sops = sops_add(sops, op_0("SBC A,[HL]")); 820 | pc += 1; 821 | break; 822 | /* SBC A,A */ 823 | case 0x9f: 824 | sops = sops_add(sops, op_0("SBC A,A")); 825 | pc += 1; 826 | break; 827 | /* AND B */ 828 | case 0xa0: 829 | sops = sops_add(sops, op_0("AND B")); 830 | pc += 1; 831 | break; 832 | /* AND C */ 833 | case 0xa1: 834 | sops = sops_add(sops, op_0("AND C")); 835 | pc += 1; 836 | break; 837 | /* AND D */ 838 | case 0xa2: 839 | sops = sops_add(sops, op_0("AND D")); 840 | pc += 1; 841 | break; 842 | /* AND E */ 843 | case 0xa3: 844 | sops = sops_add(sops, op_0("AND E")); 845 | pc += 1; 846 | break; 847 | /* AND H */ 848 | case 0xa4: 849 | sops = sops_add(sops, op_0("AND H")); 850 | pc += 1; 851 | break; 852 | /* AND L */ 853 | case 0xa5: 854 | sops = sops_add(sops, op_0("AND L")); 855 | pc += 1; 856 | break; 857 | /* AND [HL] */ 858 | case 0xa6: 859 | sops = sops_add(sops, op_0("AND [HL]")); 860 | pc += 1; 861 | break; 862 | /* AND A */ 863 | case 0xa7: 864 | sops = sops_add(sops, op_0("AND A")); 865 | pc += 1; 866 | break; 867 | /* XOR B */ 868 | case 0xa8: 869 | sops = sops_add(sops, op_0("XOR B")); 870 | pc += 1; 871 | break; 872 | /* XOR C */ 873 | case 0xa9: 874 | sops = sops_add(sops, op_0("XOR C")); 875 | pc += 1; 876 | break; 877 | /* XOR D */ 878 | case 0xaa: 879 | sops = sops_add(sops, op_0("XOR D")); 880 | pc += 1; 881 | break; 882 | /* XOR E */ 883 | case 0xab: 884 | sops = sops_add(sops, op_0("XOR E")); 885 | pc += 1; 886 | break; 887 | /* XOR H */ 888 | case 0xac: 889 | sops = sops_add(sops, op_0("XOR H")); 890 | pc += 1; 891 | break; 892 | /* XOR L */ 893 | case 0xad: 894 | sops = sops_add(sops, op_0("XOR L")); 895 | pc += 1; 896 | break; 897 | /* XOR [HL] */ 898 | case 0xae: 899 | sops = sops_add(sops, op_0("XOR [HL]")); 900 | pc += 1; 901 | break; 902 | /* XOR A */ 903 | case 0xaf: 904 | sops = sops_add(sops, op_0("XOR A")); 905 | pc += 1; 906 | break; 907 | /* OR B */ 908 | case 0xb0: 909 | sops = sops_add(sops, op_0("OR B")); 910 | pc += 1; 911 | break; 912 | /* OR C */ 913 | case 0xb1: 914 | sops = sops_add(sops, op_0("OR C")); 915 | pc += 1; 916 | break; 917 | /* OR D */ 918 | case 0xb2: 919 | sops = sops_add(sops, op_0("OR D")); 920 | pc += 1; 921 | break; 922 | /* OR E */ 923 | case 0xb3: 924 | sops = sops_add(sops, op_0("OR E")); 925 | pc += 1; 926 | break; 927 | /* OR H */ 928 | case 0xb4: 929 | sops = sops_add(sops, op_0("OR H")); 930 | pc += 1; 931 | break; 932 | /* OR L */ 933 | case 0xb5: 934 | sops = sops_add(sops, op_0("OR L")); 935 | pc += 1; 936 | break; 937 | /* OR [HL] */ 938 | case 0xb6: 939 | sops = sops_add(sops, op_0("OR [HL]")); 940 | pc += 1; 941 | break; 942 | /* OR A */ 943 | case 0xb7: 944 | sops = sops_add(sops, op_0("OR A")); 945 | pc += 1; 946 | break; 947 | /* CP B */ 948 | case 0xb8: 949 | sops = sops_add(sops, op_0("CP B")); 950 | pc += 1; 951 | break; 952 | /* CP C */ 953 | case 0xb9: 954 | sops = sops_add(sops, op_0("CP C")); 955 | pc += 1; 956 | break; 957 | /* CP D */ 958 | case 0xba: 959 | sops = sops_add(sops, op_0("CP D")); 960 | pc += 1; 961 | break; 962 | /* CP E */ 963 | case 0xbb: 964 | sops = sops_add(sops, op_0("CP E")); 965 | pc += 1; 966 | break; 967 | /* CP H */ 968 | case 0xbc: 969 | sops = sops_add(sops, op_0("CP H")); 970 | pc += 1; 971 | break; 972 | /* CP L */ 973 | case 0xbd: 974 | sops = sops_add(sops, op_0("CP L")); 975 | pc += 1; 976 | break; 977 | /* CP [HL] */ 978 | case 0xbe: 979 | sops = sops_add(sops, op_0("CP [HL]")); 980 | pc += 1; 981 | break; 982 | /* CP A */ 983 | case 0xbf: 984 | sops = sops_add(sops, op_0("CP A")); 985 | pc += 1; 986 | break; 987 | /* RET NZ */ 988 | case 0xc0: 989 | sops = sops_add(sops, op_0("RET NZ")); 990 | pc += 1; 991 | break; 992 | /* POP BC */ 993 | case 0xc1: 994 | sops = sops_add(sops, op_0("POP BC")); 995 | pc += 1; 996 | break; 997 | /* JP NZ,a16 */ 998 | case 0xc2: 999 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 1000 | sops = sops_add(sops, op_r16("JP NZ,", addr16)); 1001 | addr_buff_add(&jmp_addr, phy(addr16)); 1002 | if(jmp_follow) jmp16(addr16); else pc += 3; 1003 | break; 1004 | /* JP a16 */ 1005 | case 0xc3: 1006 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 1007 | sops = sops_add(sops, op_r16("JP ", addr16)); 1008 | addr_buff_add(&jmp_addr, phy(addr16)); 1009 | if(jmp_follow) jmpu16(addr16); else pc = start; 1010 | break; 1011 | /* CALL NZ,a16 */ 1012 | case 0xc4: 1013 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 1014 | sops = sops_add(sops, op_r16("CALL NZ,", addr16)); 1015 | addr_buff_add(&call_addr, phy(addr16)); 1016 | if(call_follow) jmp16(addr16); else pc += 3; 1017 | break; 1018 | /* PUSH BC */ 1019 | case 0xc5: 1020 | sops = sops_add(sops, op_0("PUSH BC")); 1021 | pc += 1; 1022 | break; 1023 | /* ADD A,d8 */ 1024 | case 0xc6: 1025 | addr8 = r->raw[phy(pc+1)]; 1026 | sops = sops_add(sops, op_r8("ADD A,", addr8)); 1027 | pc += 2; 1028 | break; 1029 | /* RST $00 */ 1030 | case 0xc7: 1031 | sops = sops_add(sops, op_0("RST $00")); 1032 | pc += 1; 1033 | break; 1034 | /* RET Z */ 1035 | case 0xc8: 1036 | sops = sops_add(sops, op_0("RET Z")); 1037 | pc += 1; 1038 | break; 1039 | /* RET */ 1040 | case 0xc9: 1041 | sops = sops_add(sops, op_0("RET")); 1042 | ret(); 1043 | break; 1044 | /* JP Z,a16 */ 1045 | case 0xca: 1046 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 1047 | sops = sops_add(sops, op_r16("JP Z,", addr16)); 1048 | addr_buff_add(&jmp_addr, phy(addr16)); 1049 | if(jmp_follow) jmp16(addr16); else pc += 3; 1050 | break; 1051 | /* bit operations */ 1052 | case 0xcb: 1053 | switch(r->raw[phy(pc+1)]) { 1054 | /* RLC B */ 1055 | case 0x0: 1056 | sops = sops_add(sops, op_0_2("RLC B")); 1057 | break; 1058 | /* RLC C */ 1059 | case 0x1: 1060 | sops = sops_add(sops, op_0_2("RLC C")); 1061 | break; 1062 | /* RLC D */ 1063 | case 0x2: 1064 | sops = sops_add(sops, op_0_2("RLC D")); 1065 | break; 1066 | /* RLC E */ 1067 | case 0x3: 1068 | sops = sops_add(sops, op_0_2("RLC E")); 1069 | break; 1070 | /* RLC H */ 1071 | case 0x4: 1072 | sops = sops_add(sops, op_0_2("RLC H")); 1073 | break; 1074 | /* RLC L */ 1075 | case 0x5: 1076 | sops = sops_add(sops, op_0_2("RLC L")); 1077 | break; 1078 | /* RLC [HL] */ 1079 | case 0x6: 1080 | sops = sops_add(sops, op_0_2("RLC [HL]")); 1081 | break; 1082 | /* RLC A */ 1083 | case 0x7: 1084 | sops = sops_add(sops, op_0_2("RLC A")); 1085 | break; 1086 | /* RRC B */ 1087 | case 0x8: 1088 | sops = sops_add(sops, op_0_2("RRC B")); 1089 | break; 1090 | /* RRC C */ 1091 | case 0x9: 1092 | sops = sops_add(sops, op_0_2("RRC C")); 1093 | break; 1094 | /* RRC D */ 1095 | case 0xa: 1096 | sops = sops_add(sops, op_0_2("RRC D")); 1097 | break; 1098 | /* RRC E */ 1099 | case 0xb: 1100 | sops = sops_add(sops, op_0_2("RRC E")); 1101 | break; 1102 | /* RRC H */ 1103 | case 0xc: 1104 | sops = sops_add(sops, op_0_2("RRC H")); 1105 | break; 1106 | /* RRC L */ 1107 | case 0xd: 1108 | sops = sops_add(sops, op_0_2("RRC L")); 1109 | break; 1110 | /* RRC [HL] */ 1111 | case 0xe: 1112 | sops = sops_add(sops, op_0_2("RRC [HL]")); 1113 | break; 1114 | /* RRC A */ 1115 | case 0xf: 1116 | sops = sops_add(sops, op_0_2("RRC A")); 1117 | break; 1118 | /* RL B */ 1119 | case 0x10: 1120 | sops = sops_add(sops, op_0_2("RL B")); 1121 | break; 1122 | /* RL C */ 1123 | case 0x11: 1124 | sops = sops_add(sops, op_0_2("RL C")); 1125 | break; 1126 | /* RL D */ 1127 | case 0x12: 1128 | sops = sops_add(sops, op_0_2("RL D")); 1129 | break; 1130 | /* RL E */ 1131 | case 0x13: 1132 | sops = sops_add(sops, op_0_2("RL E")); 1133 | break; 1134 | /* RL H */ 1135 | case 0x14: 1136 | sops = sops_add(sops, op_0_2("RL H")); 1137 | break; 1138 | /* RL L */ 1139 | case 0x15: 1140 | sops = sops_add(sops, op_0_2("RL L")); 1141 | break; 1142 | /* RL [HL] */ 1143 | case 0x16: 1144 | sops = sops_add(sops, op_0_2("RL [HL]")); 1145 | break; 1146 | /* RL A */ 1147 | case 0x17: 1148 | sops = sops_add(sops, op_0_2("RL A")); 1149 | break; 1150 | /* RR B */ 1151 | case 0x18: 1152 | sops = sops_add(sops, op_0_2("RR B")); 1153 | break; 1154 | /* RR C */ 1155 | case 0x19: 1156 | sops = sops_add(sops, op_0_2("RR C")); 1157 | break; 1158 | /* RR D */ 1159 | case 0x1a: 1160 | sops = sops_add(sops, op_0_2("RR D")); 1161 | break; 1162 | /* RR E */ 1163 | case 0x1b: 1164 | sops = sops_add(sops, op_0_2("RR E")); 1165 | break; 1166 | /* RR H */ 1167 | case 0x1c: 1168 | sops = sops_add(sops, op_0_2("RR H")); 1169 | break; 1170 | /* RR L */ 1171 | case 0x1d: 1172 | sops = sops_add(sops, op_0_2("RR L")); 1173 | break; 1174 | /* RR [HL] */ 1175 | case 0x1e: 1176 | sops = sops_add(sops, op_0_2("RR [HL]")); 1177 | break; 1178 | /* RR A */ 1179 | case 0x1f: 1180 | sops = sops_add(sops, op_0_2("RR A")); 1181 | break; 1182 | /* SLA B */ 1183 | case 0x20: 1184 | sops = sops_add(sops, op_0_2("SLA B")); 1185 | break; 1186 | /* SLA C */ 1187 | case 0x21: 1188 | sops = sops_add(sops, op_0_2("SLA C")); 1189 | break; 1190 | /* SLA D */ 1191 | case 0x22: 1192 | sops = sops_add(sops, op_0_2("SLA D")); 1193 | break; 1194 | /* SLA E */ 1195 | case 0x23: 1196 | sops = sops_add(sops, op_0_2("SLA E")); 1197 | break; 1198 | /* SLA H */ 1199 | case 0x24: 1200 | sops = sops_add(sops, op_0_2("SLA H")); 1201 | break; 1202 | /* SLA L */ 1203 | case 0x25: 1204 | sops = sops_add(sops, op_0_2("SLA L")); 1205 | break; 1206 | /* SLA [HL] */ 1207 | case 0x26: 1208 | sops = sops_add(sops, op_0_2("SLA [HL]")); 1209 | break; 1210 | /* SLA A */ 1211 | case 0x27: 1212 | sops = sops_add(sops, op_0_2("SLA A")); 1213 | break; 1214 | /* SRA B */ 1215 | case 0x28: 1216 | sops = sops_add(sops, op_0_2("SRA B")); 1217 | break; 1218 | /* SRA C */ 1219 | case 0x29: 1220 | sops = sops_add(sops, op_0_2("SRA C")); 1221 | break; 1222 | /* SRA D */ 1223 | case 0x2a: 1224 | sops = sops_add(sops, op_0_2("SRA D")); 1225 | break; 1226 | /* SRA E */ 1227 | case 0x2b: 1228 | sops = sops_add(sops, op_0_2("SRA E")); 1229 | break; 1230 | /* SRA H */ 1231 | case 0x2c: 1232 | sops = sops_add(sops, op_0_2("SRA H")); 1233 | break; 1234 | /* SRA L */ 1235 | case 0x2d: 1236 | sops = sops_add(sops, op_0_2("SRA L")); 1237 | break; 1238 | /* SRA [HL] */ 1239 | case 0x2e: 1240 | sops = sops_add(sops, op_0_2("SRA [HL]")); 1241 | break; 1242 | /* SRA A */ 1243 | case 0x2f: 1244 | sops = sops_add(sops, op_0_2("SRA A")); 1245 | break; 1246 | /* SWAP B */ 1247 | case 0x30: 1248 | sops = sops_add(sops, op_0_2("SWAP B")); 1249 | break; 1250 | /* SWAP C */ 1251 | case 0x31: 1252 | sops = sops_add(sops, op_0_2("SWAP C")); 1253 | break; 1254 | /* SWAP D */ 1255 | case 0x32: 1256 | sops = sops_add(sops, op_0_2("SWAP D")); 1257 | break; 1258 | /* SWAP E */ 1259 | case 0x33: 1260 | sops = sops_add(sops, op_0_2("SWAP E")); 1261 | break; 1262 | /* SWAP H */ 1263 | case 0x34: 1264 | sops = sops_add(sops, op_0_2("SWAP H")); 1265 | break; 1266 | /* SWAP L */ 1267 | case 0x35: 1268 | sops = sops_add(sops, op_0_2("SWAP L")); 1269 | break; 1270 | /* SWAP [HL] */ 1271 | case 0x36: 1272 | sops = sops_add(sops, op_0_2("SWAP [HL]")); 1273 | break; 1274 | /* SWAP A */ 1275 | case 0x37: 1276 | sops = sops_add(sops, op_0_2("SWAP A")); 1277 | break; 1278 | /* SRL B */ 1279 | case 0x38: 1280 | sops = sops_add(sops, op_0_2("SRL B")); 1281 | break; 1282 | /* SRL C */ 1283 | case 0x39: 1284 | sops = sops_add(sops, op_0_2("SRL C")); 1285 | break; 1286 | /* SRL D */ 1287 | case 0x3a: 1288 | sops = sops_add(sops, op_0_2("SRL D")); 1289 | break; 1290 | /* SRL E */ 1291 | case 0x3b: 1292 | sops = sops_add(sops, op_0_2("SRL E")); 1293 | break; 1294 | /* SRL H */ 1295 | case 0x3c: 1296 | sops = sops_add(sops, op_0_2("SRL H")); 1297 | break; 1298 | /* SRL L */ 1299 | case 0x3d: 1300 | sops = sops_add(sops, op_0_2("SRL L")); 1301 | break; 1302 | /* SRL [HL] */ 1303 | case 0x3e: 1304 | sops = sops_add(sops, op_0_2("SRL [HL]")); 1305 | break; 1306 | /* SRL A */ 1307 | case 0x3f: 1308 | sops = sops_add(sops, op_0_2("SRL A")); 1309 | break; 1310 | /* BIT 0,B */ 1311 | case 0x40: 1312 | sops = sops_add(sops, op_0_2("BIT 0,B")); 1313 | break; 1314 | /* BIT 0,C */ 1315 | case 0x41: 1316 | sops = sops_add(sops, op_0_2("BIT 0,C")); 1317 | break; 1318 | /* BIT 0,D */ 1319 | case 0x42: 1320 | sops = sops_add(sops, op_0_2("BIT 0,D")); 1321 | break; 1322 | /* BIT 0,E */ 1323 | case 0x43: 1324 | sops = sops_add(sops, op_0_2("BIT 0,E")); 1325 | break; 1326 | /* BIT 0,H */ 1327 | case 0x44: 1328 | sops = sops_add(sops, op_0_2("BIT 0,H")); 1329 | break; 1330 | /* BIT 0,L */ 1331 | case 0x45: 1332 | sops = sops_add(sops, op_0_2("BIT 0,L")); 1333 | break; 1334 | /* BIT 0,[HL] */ 1335 | case 0x46: 1336 | sops = sops_add(sops, op_0_2("BIT 0,[HL]")); 1337 | break; 1338 | /* BIT 0,A */ 1339 | case 0x47: 1340 | sops = sops_add(sops, op_0_2("BIT 0,A")); 1341 | break; 1342 | /* BIT 1,B */ 1343 | case 0x48: 1344 | sops = sops_add(sops, op_0_2("BIT 1,B")); 1345 | break; 1346 | /* BIT 1,C */ 1347 | case 0x49: 1348 | sops = sops_add(sops, op_0_2("BIT 1,C")); 1349 | break; 1350 | /* BIT 1,D */ 1351 | case 0x4a: 1352 | sops = sops_add(sops, op_0_2("BIT 1,D")); 1353 | break; 1354 | /* BIT 1,E */ 1355 | case 0x4b: 1356 | sops = sops_add(sops, op_0_2("BIT 1,E")); 1357 | break; 1358 | /* BIT 1,H */ 1359 | case 0x4c: 1360 | sops = sops_add(sops, op_0_2("BIT 1,H")); 1361 | break; 1362 | /* BIT 1,L */ 1363 | case 0x4d: 1364 | sops = sops_add(sops, op_0_2("BIT 1,L")); 1365 | break; 1366 | /* BIT 1,[HL] */ 1367 | case 0x4e: 1368 | sops = sops_add(sops, op_0_2("BIT 1,[HL]")); 1369 | break; 1370 | /* BIT 1,A */ 1371 | case 0x4f: 1372 | sops = sops_add(sops, op_0_2("BIT 1,A")); 1373 | break; 1374 | /* BIT 2,B */ 1375 | case 0x50: 1376 | sops = sops_add(sops, op_0_2("BIT 2,B")); 1377 | break; 1378 | /* BIT 2,C */ 1379 | case 0x51: 1380 | sops = sops_add(sops, op_0_2("BIT 2,C")); 1381 | break; 1382 | /* BIT 2,D */ 1383 | case 0x52: 1384 | sops = sops_add(sops, op_0_2("BIT 2,D")); 1385 | break; 1386 | /* BIT 2,E */ 1387 | case 0x53: 1388 | sops = sops_add(sops, op_0_2("BIT 2,E")); 1389 | break; 1390 | /* BIT 2,H */ 1391 | case 0x54: 1392 | sops = sops_add(sops, op_0_2("BIT 2,H")); 1393 | break; 1394 | /* BIT 2,L */ 1395 | case 0x55: 1396 | sops = sops_add(sops, op_0_2("BIT 2,L")); 1397 | break; 1398 | /* BIT 2,[HL] */ 1399 | case 0x56: 1400 | sops = sops_add(sops, op_0_2("BIT 2,[HL]")); 1401 | break; 1402 | /* BIT 2,A */ 1403 | case 0x57: 1404 | sops = sops_add(sops, op_0_2("BIT 2,A")); 1405 | break; 1406 | /* BIT 3,B */ 1407 | case 0x58: 1408 | sops = sops_add(sops, op_0_2("BIT 3,B")); 1409 | break; 1410 | /* BIT 3,C */ 1411 | case 0x59: 1412 | sops = sops_add(sops, op_0_2("BIT 3,C")); 1413 | break; 1414 | /* BIT 3,D */ 1415 | case 0x5a: 1416 | sops = sops_add(sops, op_0_2("BIT 3,D")); 1417 | break; 1418 | /* BIT 3,E */ 1419 | case 0x5b: 1420 | sops = sops_add(sops, op_0_2("BIT 3,E")); 1421 | break; 1422 | /* BIT 3,H */ 1423 | case 0x5c: 1424 | sops = sops_add(sops, op_0_2("BIT 3,H")); 1425 | break; 1426 | /* BIT 3,L */ 1427 | case 0x5d: 1428 | sops = sops_add(sops, op_0_2("BIT 3,L")); 1429 | break; 1430 | /* BIT 3,[HL] */ 1431 | case 0x5e: 1432 | sops = sops_add(sops, op_0_2("BIT 3,[HL]")); 1433 | break; 1434 | /* BIT 3,A */ 1435 | case 0x5f: 1436 | sops = sops_add(sops, op_0_2("BIT 3,A")); 1437 | break; 1438 | /* BIT 4,B */ 1439 | case 0x60: 1440 | sops = sops_add(sops, op_0_2("BIT 4,B")); 1441 | break; 1442 | /* BIT 4,C */ 1443 | case 0x61: 1444 | sops = sops_add(sops, op_0_2("BIT 4,C")); 1445 | break; 1446 | /* BIT 4,D */ 1447 | case 0x62: 1448 | sops = sops_add(sops, op_0_2("BIT 4,D")); 1449 | break; 1450 | /* BIT 4,E */ 1451 | case 0x63: 1452 | sops = sops_add(sops, op_0_2("BIT 4,E")); 1453 | break; 1454 | /* BIT 4,H */ 1455 | case 0x64: 1456 | sops = sops_add(sops, op_0_2("BIT 4,H")); 1457 | break; 1458 | /* BIT 4,L */ 1459 | case 0x65: 1460 | sops = sops_add(sops, op_0_2("BIT 4,L")); 1461 | break; 1462 | /* BIT 4,[HL] */ 1463 | case 0x66: 1464 | sops = sops_add(sops, op_0_2("BIT 4,[HL]")); 1465 | break; 1466 | /* BIT 4,A */ 1467 | case 0x67: 1468 | sops = sops_add(sops, op_0_2("BIT 4,A")); 1469 | break; 1470 | /* BIT 5,B */ 1471 | case 0x68: 1472 | sops = sops_add(sops, op_0_2("BIT 5,B")); 1473 | break; 1474 | /* BIT 5,C */ 1475 | case 0x69: 1476 | sops = sops_add(sops, op_0_2("BIT 5,C")); 1477 | break; 1478 | /* BIT 5,D */ 1479 | case 0x6a: 1480 | sops = sops_add(sops, op_0_2("BIT 5,D")); 1481 | break; 1482 | /* BIT 5,E */ 1483 | case 0x6b: 1484 | sops = sops_add(sops, op_0_2("BIT 5,E")); 1485 | break; 1486 | /* BIT 5,H */ 1487 | case 0x6c: 1488 | sops = sops_add(sops, op_0_2("BIT 5,H")); 1489 | break; 1490 | /* BIT 5,L */ 1491 | case 0x6d: 1492 | sops = sops_add(sops, op_0_2("BIT 5,L")); 1493 | break; 1494 | /* BIT 5,[HL] */ 1495 | case 0x6e: 1496 | sops = sops_add(sops, op_0_2("BIT 5,[HL]")); 1497 | break; 1498 | /* BIT 5,A */ 1499 | case 0x6f: 1500 | sops = sops_add(sops, op_0_2("BIT 5,A")); 1501 | break; 1502 | /* BIT 6,B */ 1503 | case 0x70: 1504 | sops = sops_add(sops, op_0_2("BIT 6,B")); 1505 | break; 1506 | /* BIT 6,C */ 1507 | case 0x71: 1508 | sops = sops_add(sops, op_0_2("BIT 6,C")); 1509 | break; 1510 | /* BIT 6,D */ 1511 | case 0x72: 1512 | sops = sops_add(sops, op_0_2("BIT 6,D")); 1513 | break; 1514 | /* BIT 6,E */ 1515 | case 0x73: 1516 | sops = sops_add(sops, op_0_2("BIT 6,E")); 1517 | break; 1518 | /* BIT 6,H */ 1519 | case 0x74: 1520 | sops = sops_add(sops, op_0_2("BIT 6,H")); 1521 | break; 1522 | /* BIT 6,L */ 1523 | case 0x75: 1524 | sops = sops_add(sops, op_0_2("BIT 6,L")); 1525 | break; 1526 | /* BIT 6,[HL] */ 1527 | case 0x76: 1528 | sops = sops_add(sops, op_0_2("BIT 6,[HL]")); 1529 | break; 1530 | /* BIT 6,A */ 1531 | case 0x77: 1532 | sops = sops_add(sops, op_0_2("BIT 6,A")); 1533 | break; 1534 | /* BIT 7,B */ 1535 | case 0x78: 1536 | sops = sops_add(sops, op_0_2("BIT 7,B")); 1537 | break; 1538 | /* BIT 7,C */ 1539 | case 0x79: 1540 | sops = sops_add(sops, op_0_2("BIT 7,C")); 1541 | break; 1542 | /* BIT 7,D */ 1543 | case 0x7a: 1544 | sops = sops_add(sops, op_0_2("BIT 7,D")); 1545 | break; 1546 | /* BIT 7,E */ 1547 | case 0x7b: 1548 | sops = sops_add(sops, op_0_2("BIT 7,E")); 1549 | break; 1550 | /* BIT 7,H */ 1551 | case 0x7c: 1552 | sops = sops_add(sops, op_0_2("BIT 7,H")); 1553 | break; 1554 | /* BIT 7,L */ 1555 | case 0x7d: 1556 | sops = sops_add(sops, op_0_2("BIT 7,L")); 1557 | break; 1558 | /* BIT 7,[HL] */ 1559 | case 0x7e: 1560 | sops = sops_add(sops, op_0_2("BIT 7,[HL]")); 1561 | break; 1562 | /* BIT 7,A */ 1563 | case 0x7f: 1564 | sops = sops_add(sops, op_0_2("BIT 7,A")); 1565 | break; 1566 | /* RES 0,B */ 1567 | case 0x80: 1568 | sops = sops_add(sops, op_0_2("RES 0,B")); 1569 | break; 1570 | /* RES 0,C */ 1571 | case 0x81: 1572 | sops = sops_add(sops, op_0_2("RES 0,C")); 1573 | break; 1574 | /* RES 0,D */ 1575 | case 0x82: 1576 | sops = sops_add(sops, op_0_2("RES 0,D")); 1577 | break; 1578 | /* RES 0,E */ 1579 | case 0x83: 1580 | sops = sops_add(sops, op_0_2("RES 0,E")); 1581 | break; 1582 | /* RES 0,H */ 1583 | case 0x84: 1584 | sops = sops_add(sops, op_0_2("RES 0,H")); 1585 | break; 1586 | /* RES 0,L */ 1587 | case 0x85: 1588 | sops = sops_add(sops, op_0_2("RES 0,L")); 1589 | break; 1590 | /* RES 0,[HL] */ 1591 | case 0x86: 1592 | sops = sops_add(sops, op_0_2("RES 0,[HL]")); 1593 | break; 1594 | /* RES 0,A */ 1595 | case 0x87: 1596 | sops = sops_add(sops, op_0_2("RES 0,A")); 1597 | break; 1598 | /* RES 1,B */ 1599 | case 0x88: 1600 | sops = sops_add(sops, op_0_2("RES 1,B")); 1601 | break; 1602 | /* RES 1,C */ 1603 | case 0x89: 1604 | sops = sops_add(sops, op_0_2("RES 1,C")); 1605 | break; 1606 | /* RES 1,D */ 1607 | case 0x8a: 1608 | sops = sops_add(sops, op_0_2("RES 1,D")); 1609 | break; 1610 | /* RES 1,E */ 1611 | case 0x8b: 1612 | sops = sops_add(sops, op_0_2("RES 1,E")); 1613 | break; 1614 | /* RES 1,H */ 1615 | case 0x8c: 1616 | sops = sops_add(sops, op_0_2("RES 1,H")); 1617 | break; 1618 | /* RES 1,L */ 1619 | case 0x8d: 1620 | sops = sops_add(sops, op_0_2("RES 1,L")); 1621 | break; 1622 | /* RES 1,[HL] */ 1623 | case 0x8e: 1624 | sops = sops_add(sops, op_0_2("RES 1,[HL]")); 1625 | break; 1626 | /* RES 1,A */ 1627 | case 0x8f: 1628 | sops = sops_add(sops, op_0_2("RES 1,A")); 1629 | break; 1630 | /* RES 2,B */ 1631 | case 0x90: 1632 | sops = sops_add(sops, op_0_2("RES 2,B")); 1633 | break; 1634 | /* RES 2,C */ 1635 | case 0x91: 1636 | sops = sops_add(sops, op_0_2("RES 2,C")); 1637 | break; 1638 | /* RES 2,D */ 1639 | case 0x92: 1640 | sops = sops_add(sops, op_0_2("RES 2,D")); 1641 | break; 1642 | /* RES 2,E */ 1643 | case 0x93: 1644 | sops = sops_add(sops, op_0_2("RES 2,E")); 1645 | break; 1646 | /* RES 2,H */ 1647 | case 0x94: 1648 | sops = sops_add(sops, op_0_2("RES 2,H")); 1649 | break; 1650 | /* RES 2,L */ 1651 | case 0x95: 1652 | sops = sops_add(sops, op_0_2("RES 2,L")); 1653 | break; 1654 | /* RES 2,[HL] */ 1655 | case 0x96: 1656 | sops = sops_add(sops, op_0_2("RES 2,[HL]")); 1657 | break; 1658 | /* RES 2,A */ 1659 | case 0x97: 1660 | sops = sops_add(sops, op_0_2("RES 2,A")); 1661 | break; 1662 | /* RES 3,B */ 1663 | case 0x98: 1664 | sops = sops_add(sops, op_0_2("RES 3,B")); 1665 | break; 1666 | /* RES 3,C */ 1667 | case 0x99: 1668 | sops = sops_add(sops, op_0_2("RES 3,C")); 1669 | break; 1670 | /* RES 3,D */ 1671 | case 0x9a: 1672 | sops = sops_add(sops, op_0_2("RES 3,D")); 1673 | break; 1674 | /* RES 3,E */ 1675 | case 0x9b: 1676 | sops = sops_add(sops, op_0_2("RES 3,E")); 1677 | break; 1678 | /* RES 3,H */ 1679 | case 0x9c: 1680 | sops = sops_add(sops, op_0_2("RES 3,H")); 1681 | break; 1682 | /* RES 3,L */ 1683 | case 0x9d: 1684 | sops = sops_add(sops, op_0_2("RES 3,L")); 1685 | break; 1686 | /* RES 3,[HL] */ 1687 | case 0x9e: 1688 | sops = sops_add(sops, op_0_2("RES 3,[HL]")); 1689 | break; 1690 | /* RES 3,A */ 1691 | case 0x9f: 1692 | sops = sops_add(sops, op_0_2("RES 3,A")); 1693 | break; 1694 | /* RES 4,B */ 1695 | case 0xa0: 1696 | sops = sops_add(sops, op_0_2("RES 4,B")); 1697 | break; 1698 | /* RES 4,C */ 1699 | case 0xa1: 1700 | sops = sops_add(sops, op_0_2("RES 4,C")); 1701 | break; 1702 | /* RES 4,D */ 1703 | case 0xa2: 1704 | sops = sops_add(sops, op_0_2("RES 4,D")); 1705 | break; 1706 | /* RES 4,E */ 1707 | case 0xa3: 1708 | sops = sops_add(sops, op_0_2("RES 4,E")); 1709 | break; 1710 | /* RES 4,H */ 1711 | case 0xa4: 1712 | sops = sops_add(sops, op_0_2("RES 4,H")); 1713 | break; 1714 | /* RES 4,L */ 1715 | case 0xa5: 1716 | sops = sops_add(sops, op_0_2("RES 4,L")); 1717 | break; 1718 | /* RES 4,[HL] */ 1719 | case 0xa6: 1720 | sops = sops_add(sops, op_0_2("RES 4,[HL]")); 1721 | break; 1722 | /* RES 4,A */ 1723 | case 0xa7: 1724 | sops = sops_add(sops, op_0_2("RES 4,A")); 1725 | break; 1726 | /* RES 5,B */ 1727 | case 0xa8: 1728 | sops = sops_add(sops, op_0_2("RES 5,B")); 1729 | break; 1730 | /* RES 5,C */ 1731 | case 0xa9: 1732 | sops = sops_add(sops, op_0_2("RES 5,C")); 1733 | break; 1734 | /* RES 5,D */ 1735 | case 0xaa: 1736 | sops = sops_add(sops, op_0_2("RES 5,D")); 1737 | break; 1738 | /* RES 5,E */ 1739 | case 0xab: 1740 | sops = sops_add(sops, op_0_2("RES 5,E")); 1741 | break; 1742 | /* RES 5,H */ 1743 | case 0xac: 1744 | sops = sops_add(sops, op_0_2("RES 5,H")); 1745 | break; 1746 | /* RES 5,L */ 1747 | case 0xad: 1748 | sops = sops_add(sops, op_0_2("RES 5,L")); 1749 | break; 1750 | /* RES 5,[HL] */ 1751 | case 0xae: 1752 | sops = sops_add(sops, op_0_2("RES 5,[HL]")); 1753 | break; 1754 | /* RES 5,A */ 1755 | case 0xaf: 1756 | sops = sops_add(sops, op_0_2("RES 5,A")); 1757 | break; 1758 | /* RES 6,B */ 1759 | case 0xb0: 1760 | sops = sops_add(sops, op_0_2("RES 6,B")); 1761 | break; 1762 | /* RES 6,C */ 1763 | case 0xb1: 1764 | sops = sops_add(sops, op_0_2("RES 6,C")); 1765 | break; 1766 | /* RES 6,D */ 1767 | case 0xb2: 1768 | sops = sops_add(sops, op_0_2("RES 6,D")); 1769 | break; 1770 | /* RES 6,E */ 1771 | case 0xb3: 1772 | sops = sops_add(sops, op_0_2("RES 6,E")); 1773 | break; 1774 | /* RES 6,H */ 1775 | case 0xb4: 1776 | sops = sops_add(sops, op_0_2("RES 6,H")); 1777 | break; 1778 | /* RES 6,L */ 1779 | case 0xb5: 1780 | sops = sops_add(sops, op_0_2("RES 6,L")); 1781 | break; 1782 | /* RES 6,[HL] */ 1783 | case 0xb6: 1784 | sops = sops_add(sops, op_0_2("RES 6,[HL]")); 1785 | break; 1786 | /* RES 6,A */ 1787 | case 0xb7: 1788 | sops = sops_add(sops, op_0_2("RES 6,A")); 1789 | break; 1790 | /* RES 7,B */ 1791 | case 0xb8: 1792 | sops = sops_add(sops, op_0_2("RES 7,B")); 1793 | break; 1794 | /* RES 7,C */ 1795 | case 0xb9: 1796 | sops = sops_add(sops, op_0_2("RES 7,C")); 1797 | break; 1798 | /* RES 7,D */ 1799 | case 0xba: 1800 | sops = sops_add(sops, op_0_2("RES 7,D")); 1801 | break; 1802 | /* RES 7,E */ 1803 | case 0xbb: 1804 | sops = sops_add(sops, op_0_2("RES 7,E")); 1805 | break; 1806 | /* RES 7,H */ 1807 | case 0xbc: 1808 | sops = sops_add(sops, op_0_2("RES 7,H")); 1809 | break; 1810 | /* RES 7,L */ 1811 | case 0xbd: 1812 | sops = sops_add(sops, op_0_2("RES 7,L")); 1813 | break; 1814 | /* RES 7,[HL] */ 1815 | case 0xbe: 1816 | sops = sops_add(sops, op_0_2("RES 7,[HL]")); 1817 | break; 1818 | /* RES 7,A */ 1819 | case 0xbf: 1820 | sops = sops_add(sops, op_0_2("RES 7,A")); 1821 | break; 1822 | /* SET 0,B */ 1823 | case 0xc0: 1824 | sops = sops_add(sops, op_0_2("SET 0,B")); 1825 | break; 1826 | /* SET 0,C */ 1827 | case 0xc1: 1828 | sops = sops_add(sops, op_0_2("SET 0,C")); 1829 | break; 1830 | /* SET 0,D */ 1831 | case 0xc2: 1832 | sops = sops_add(sops, op_0_2("SET 0,D")); 1833 | break; 1834 | /* SET 0,E */ 1835 | case 0xc3: 1836 | sops = sops_add(sops, op_0_2("SET 0,E")); 1837 | break; 1838 | /* SET 0,H */ 1839 | case 0xc4: 1840 | sops = sops_add(sops, op_0_2("SET 0,H")); 1841 | break; 1842 | /* SET 0,L */ 1843 | case 0xc5: 1844 | sops = sops_add(sops, op_0_2("SET 0,L")); 1845 | break; 1846 | /* SET 0,[HL] */ 1847 | case 0xc6: 1848 | sops = sops_add(sops, op_0_2("SET 0,[HL]")); 1849 | break; 1850 | /* SET 0,A */ 1851 | case 0xc7: 1852 | sops = sops_add(sops, op_0_2("SET 0,A")); 1853 | break; 1854 | /* SET 1,B */ 1855 | case 0xc8: 1856 | sops = sops_add(sops, op_0_2("SET 1,B")); 1857 | break; 1858 | /* SET 1,C */ 1859 | case 0xc9: 1860 | sops = sops_add(sops, op_0_2("SET 1,C")); 1861 | break; 1862 | /* SET 1,D */ 1863 | case 0xca: 1864 | sops = sops_add(sops, op_0_2("SET 1,D")); 1865 | break; 1866 | /* SET 1,E */ 1867 | case 0xcb: 1868 | sops = sops_add(sops, op_0_2("SET 1,E")); 1869 | break; 1870 | /* SET 1,H */ 1871 | case 0xcc: 1872 | sops = sops_add(sops, op_0_2("SET 1,H")); 1873 | break; 1874 | /* SET 1,L */ 1875 | case 0xcd: 1876 | sops = sops_add(sops, op_0_2("SET 1,L")); 1877 | break; 1878 | /* SET 1,[HL] */ 1879 | case 0xce: 1880 | sops = sops_add(sops, op_0_2("SET 1,[HL]")); 1881 | break; 1882 | /* SET 1,A */ 1883 | case 0xcf: 1884 | sops = sops_add(sops, op_0_2("SET 1,A")); 1885 | break; 1886 | /* SET 2,B */ 1887 | case 0xd0: 1888 | sops = sops_add(sops, op_0_2("SET 2,B")); 1889 | break; 1890 | /* SET 2,C */ 1891 | case 0xd1: 1892 | sops = sops_add(sops, op_0_2("SET 2,C")); 1893 | break; 1894 | /* SET 2,D */ 1895 | case 0xd2: 1896 | sops = sops_add(sops, op_0_2("SET 2,D")); 1897 | break; 1898 | /* SET 2,E */ 1899 | case 0xd3: 1900 | sops = sops_add(sops, op_0_2("SET 2,E")); 1901 | break; 1902 | /* SET 2,H */ 1903 | case 0xd4: 1904 | sops = sops_add(sops, op_0_2("SET 2,H")); 1905 | break; 1906 | /* SET 2,L */ 1907 | case 0xd5: 1908 | sops = sops_add(sops, op_0_2("SET 2,L")); 1909 | break; 1910 | /* SET 2,[HL] */ 1911 | case 0xd6: 1912 | sops = sops_add(sops, op_0_2("SET 2,[HL]")); 1913 | break; 1914 | /* SET 2,A */ 1915 | case 0xd7: 1916 | sops = sops_add(sops, op_0_2("SET 2,A")); 1917 | break; 1918 | /* SET 3,B */ 1919 | case 0xd8: 1920 | sops = sops_add(sops, op_0_2("SET 3,B")); 1921 | break; 1922 | /* SET 3,C */ 1923 | case 0xd9: 1924 | sops = sops_add(sops, op_0_2("SET 3,C")); 1925 | break; 1926 | /* SET 3,D */ 1927 | case 0xda: 1928 | sops = sops_add(sops, op_0_2("SET 3,D")); 1929 | break; 1930 | /* SET 3,E */ 1931 | case 0xdb: 1932 | sops = sops_add(sops, op_0_2("SET 3,E")); 1933 | break; 1934 | /* SET 3,H */ 1935 | case 0xdc: 1936 | sops = sops_add(sops, op_0_2("SET 3,H")); 1937 | break; 1938 | /* SET 3,L */ 1939 | case 0xdd: 1940 | sops = sops_add(sops, op_0_2("SET 3,L")); 1941 | break; 1942 | /* SET 3,[HL] */ 1943 | case 0xde: 1944 | sops = sops_add(sops, op_0_2("SET 3,[HL]")); 1945 | break; 1946 | /* SET 3,A */ 1947 | case 0xdf: 1948 | sops = sops_add(sops, op_0_2("SET 3,A")); 1949 | break; 1950 | /* SET 4,B */ 1951 | case 0xe0: 1952 | sops = sops_add(sops, op_0_2("SET 4,B")); 1953 | break; 1954 | /* SET 4,C */ 1955 | case 0xe1: 1956 | sops = sops_add(sops, op_0_2("SET 4,C")); 1957 | break; 1958 | /* SET 4,D */ 1959 | case 0xe2: 1960 | sops = sops_add(sops, op_0_2("SET 4,D")); 1961 | break; 1962 | /* SET 4,E */ 1963 | case 0xe3: 1964 | sops = sops_add(sops, op_0_2("SET 4,E")); 1965 | break; 1966 | /* SET 4,H */ 1967 | case 0xe4: 1968 | sops = sops_add(sops, op_0_2("SET 4,H")); 1969 | break; 1970 | /* SET 4,L */ 1971 | case 0xe5: 1972 | sops = sops_add(sops, op_0_2("SET 4,L")); 1973 | break; 1974 | /* SET 4,[HL] */ 1975 | case 0xe6: 1976 | sops = sops_add(sops, op_0_2("SET 4,[HL]")); 1977 | break; 1978 | /* SET 4,A */ 1979 | case 0xe7: 1980 | sops = sops_add(sops, op_0_2("SET 4,A")); 1981 | break; 1982 | /* SET 5,B */ 1983 | case 0xe8: 1984 | sops = sops_add(sops, op_0_2("SET 5,B")); 1985 | break; 1986 | /* SET 5,C */ 1987 | case 0xe9: 1988 | sops = sops_add(sops, op_0_2("SET 5,C")); 1989 | break; 1990 | /* SET 5,D */ 1991 | case 0xea: 1992 | sops = sops_add(sops, op_0_2("SET 5,D")); 1993 | break; 1994 | /* SET 5,E */ 1995 | case 0xeb: 1996 | sops = sops_add(sops, op_0_2("SET 5,E")); 1997 | break; 1998 | /* SET 5,H */ 1999 | case 0xec: 2000 | sops = sops_add(sops, op_0_2("SET 5,H")); 2001 | break; 2002 | /* SET 5,L */ 2003 | case 0xed: 2004 | sops = sops_add(sops, op_0_2("SET 5,L")); 2005 | break; 2006 | /* SET 5,[HL] */ 2007 | case 0xee: 2008 | sops = sops_add(sops, op_0_2("SET 5,[HL]")); 2009 | break; 2010 | /* SET 5,A */ 2011 | case 0xef: 2012 | sops = sops_add(sops, op_0_2("SET 5,A")); 2013 | break; 2014 | /* SET 6,B */ 2015 | case 0xf0: 2016 | sops = sops_add(sops, op_0_2("SET 6,B")); 2017 | break; 2018 | /* SET 6,C */ 2019 | case 0xf1: 2020 | sops = sops_add(sops, op_0_2("SET 6,C")); 2021 | break; 2022 | /* SET 6,D */ 2023 | case 0xf2: 2024 | sops = sops_add(sops, op_0_2("SET 6,D")); 2025 | break; 2026 | /* SET 6,E */ 2027 | case 0xf3: 2028 | sops = sops_add(sops, op_0_2("SET 6,E")); 2029 | break; 2030 | /* SET 6,H */ 2031 | case 0xf4: 2032 | sops = sops_add(sops, op_0_2("SET 6,H")); 2033 | break; 2034 | /* SET 6,L */ 2035 | case 0xf5: 2036 | sops = sops_add(sops, op_0_2("SET 6,L")); 2037 | break; 2038 | /* SET 6,[HL] */ 2039 | case 0xf6: 2040 | sops = sops_add(sops, op_0_2("SET 6,[HL]")); 2041 | break; 2042 | /* SET 6,A */ 2043 | case 0xf7: 2044 | sops = sops_add(sops, op_0_2("SET 6,A")); 2045 | break; 2046 | /* SET 7,B */ 2047 | case 0xf8: 2048 | sops = sops_add(sops, op_0_2("SET 7,B")); 2049 | break; 2050 | /* SET 7,C */ 2051 | case 0xf9: 2052 | sops = sops_add(sops, op_0_2("SET 7,C")); 2053 | break; 2054 | /* SET 7,D */ 2055 | case 0xfa: 2056 | sops = sops_add(sops, op_0_2("SET 7,D")); 2057 | break; 2058 | /* SET 7,E */ 2059 | case 0xfb: 2060 | sops = sops_add(sops, op_0_2("SET 7,E")); 2061 | break; 2062 | /* SET 7,H */ 2063 | case 0xfc: 2064 | sops = sops_add(sops, op_0_2("SET 7,H")); 2065 | break; 2066 | /* SET 7,L */ 2067 | case 0xfd: 2068 | sops = sops_add(sops, op_0_2("SET 7,L")); 2069 | break; 2070 | /* SET 7,[HL] */ 2071 | case 0xfe: 2072 | sops = sops_add(sops, op_0_2("SET 7,[HL]")); 2073 | break; 2074 | /* SET 7,A */ 2075 | case 0xff: 2076 | sops = sops_add(sops, op_0_2("SET 7,A")); 2077 | break; 2078 | } 2079 | pc += 2; 2080 | break; 2081 | /* CALL Z,a16 */ 2082 | case 0xcc: 2083 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 2084 | sops = sops_add(sops, op_r16("CALL Z,", addr16)); 2085 | addr_buff_add(&call_addr, phy(addr16)); 2086 | if(call_follow) jmp16(addr16); else pc += 3; 2087 | break; 2088 | /* CALL a16 */ 2089 | case 0xcd: 2090 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 2091 | sops = sops_add(sops, op_r16("CALL ", addr16)); 2092 | addr_buff_add(&call_addr, phy(addr16)); 2093 | if(call_follow) jmp16(addr16); else pc += 3; 2094 | break; 2095 | /* ADC A,d8 */ 2096 | case 0xce: 2097 | addr8 = r->raw[phy(pc+1)]; 2098 | sops = sops_add(sops, op_r8("ADC A,", addr8)); 2099 | pc += 2; 2100 | break; 2101 | /* RST $08 */ 2102 | case 0xcf: 2103 | sops = sops_add(sops, op_0("RST $08")); 2104 | pc += 1; 2105 | break; 2106 | /* RET NC */ 2107 | case 0xd0: 2108 | sops = sops_add(sops, op_0("RET NC")); 2109 | pc += 1; 2110 | break; 2111 | /* POP DE */ 2112 | case 0xd1: 2113 | sops = sops_add(sops, op_0("POP DE")); 2114 | pc += 1; 2115 | break; 2116 | /* JP NC,a16 */ 2117 | case 0xd2: 2118 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 2119 | sops = sops_add(sops, op_r16("JP NC,", addr16)); 2120 | addr_buff_add(&jmp_addr, phy(addr16)); 2121 | if(jmp_follow) jmp16(addr16); else pc += 3; 2122 | break; 2123 | /* CALL NC,a16 */ 2124 | case 0xd4: 2125 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 2126 | sops = sops_add(sops, op_r16("CALL NC,", addr16)); 2127 | addr_buff_add(&call_addr, phy(addr16)); 2128 | if(call_follow) jmp16(addr16); else pc += 3; 2129 | break; 2130 | /* PUSH DE */ 2131 | case 0xd5: 2132 | sops = sops_add(sops, op_0("PUSH DE")); 2133 | pc += 1; 2134 | break; 2135 | /* SUB d8 */ 2136 | case 0xd6: 2137 | addr8 = r->raw[phy(pc+1)]; 2138 | sops = sops_add(sops, op_r8("SUB ", addr8)); 2139 | pc += 2; 2140 | break; 2141 | /* RST $10 */ 2142 | case 0xd7: 2143 | sops = sops_add(sops, op_0("RST $10")); 2144 | pc += 1; 2145 | break; 2146 | /* RET C */ 2147 | case 0xd8: 2148 | sops = sops_add(sops, op_0("RET C")); 2149 | pc += 1; 2150 | break; 2151 | /* RETI */ 2152 | case 0xd9: 2153 | sops = sops_add(sops, op_0("RETI")); 2154 | ret(); 2155 | break; 2156 | /* JP C,a16 */ 2157 | case 0xda: 2158 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 2159 | sops = sops_add(sops, op_r16("JP C,", addr16)); 2160 | addr_buff_add(&jmp_addr, phy(addr16)); 2161 | if(jmp_follow) jmp16(addr16); else pc += 3; 2162 | break; 2163 | /* CALL C,a16 */ 2164 | case 0xdc: 2165 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 2166 | sops = sops_add(sops, op_r16("CALL C,", addr16)); 2167 | addr_buff_add(&call_addr, phy(addr16)); 2168 | if(call_follow) jmp16(addr16); else pc += 3; 2169 | break; 2170 | /* SBC A,d8 */ 2171 | case 0xde: 2172 | addr8 = r->raw[phy(pc+1)]; 2173 | sops = sops_add(sops, op_r8("SBC A,", addr8)); 2174 | pc += 2; 2175 | break; 2176 | /* RST $18 */ 2177 | case 0xdf: 2178 | sops = sops_add(sops, op_0("RST $18")); 2179 | pc += 1; 2180 | break; 2181 | /* LDH [a8],A */ 2182 | case 0xe0: 2183 | addr8 = r->raw[phy(pc+1)]; 2184 | sops = sops_add(sops, op_l8("LDH [", addr8, "],A")); 2185 | hmem[addr8] = a; 2186 | pc += 2; 2187 | break; 2188 | /* POP HL */ 2189 | case 0xe1: 2190 | sops = sops_add(sops, op_0("POP HL")); 2191 | pc += 1; 2192 | break; 2193 | /* LD [C],A */ 2194 | case 0xe2: 2195 | sops = sops_add(sops, op_0("LD [C],A")); 2196 | pc += 1; 2197 | break; 2198 | /* PUSH HL */ 2199 | case 0xe5: 2200 | sops = sops_add(sops, op_0("PUSH HL")); 2201 | pc += 1; 2202 | break; 2203 | /* AND d8 */ 2204 | case 0xe6: 2205 | addr8 = r->raw[phy(pc+1)]; 2206 | sops = sops_add(sops, op_r8("AND ", addr8)); 2207 | pc += 2; 2208 | break; 2209 | /* RST $20 */ 2210 | case 0xe7: 2211 | sops = sops_add(sops, op_0("RST $20")); 2212 | pc += 1; 2213 | break; 2214 | /* ADD SP,r8 */ 2215 | case 0xe8: 2216 | addr8 = r->raw[phy(pc+1)]; 2217 | sops = sops_add(sops, op_r8("ADD SP,", addr8)); 2218 | pc += 2; 2219 | break; 2220 | /* JP [HL] */ 2221 | case 0xe9: 2222 | sops = sops_add(sops, op_0("JP [HL]")); 2223 | pc += 1; 2224 | break; 2225 | /* LD [a16],A */ 2226 | case 0xea: 2227 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 2228 | sops = sops_add(sops, op_l16("LD [", addr16, "],A")); 2229 | if(mbc != ROM_ONLY && (addr16 == 0x2000 || addr16 == 0x2100)) { 2230 | printf("Info: Bank switch to %d at 0x%.8X\n", bank, phy(pc)); 2231 | bank = a; 2232 | } 2233 | pc += 3; 2234 | break; 2235 | /* XOR d8 */ 2236 | case 0xee: 2237 | addr8 = r->raw[phy(pc+1)]; 2238 | sops = sops_add(sops, op_r8("XOR ", addr8)); 2239 | pc += 2; 2240 | break; 2241 | /* RST $28 */ 2242 | case 0xef: 2243 | sops = sops_add(sops, op_0("RST $28")); 2244 | pc += 1; 2245 | break; 2246 | /* LDH A,[a8] */ 2247 | case 0xf0: 2248 | addr8 = r->raw[phy(pc+1)]; 2249 | sops = sops_add(sops, op_l8("LDH A,[", addr8, "]")); 2250 | a = hmem[addr8]; 2251 | pc += 2; 2252 | break; 2253 | /* POP AF */ 2254 | case 0xf1: 2255 | sops = sops_add(sops, op_0("POP AF")); 2256 | pc += 1; 2257 | break; 2258 | /* LD A,[C] */ 2259 | case 0xf2: 2260 | sops = sops_add(sops, op_0("LD A,[C]")); 2261 | pc += 1; 2262 | break; 2263 | /* DI */ 2264 | case 0xf3: 2265 | sops = sops_add(sops, op_0("DI")); 2266 | pc += 1; 2267 | break; 2268 | /* PUSH AF */ 2269 | case 0xf5: 2270 | sops = sops_add(sops, op_0("PUSH AF")); 2271 | pc += 1; 2272 | break; 2273 | /* OR d8 */ 2274 | case 0xf6: 2275 | addr8 = r->raw[phy(pc+1)]; 2276 | sops = sops_add(sops, op_r8("OR ", addr8)); 2277 | pc += 2; 2278 | break; 2279 | /* RST $30 */ 2280 | case 0xf7: 2281 | sops = sops_add(sops, op_0("RST $30")); 2282 | pc += 1; 2283 | break; 2284 | /* LD HL,SP+r8 */ 2285 | case 0xf8: 2286 | addr8 = r->raw[phy(pc+1)]; 2287 | sops = sops_add(sops, op_r8("LD HL,SP+", addr8)); 2288 | pc += 2; 2289 | break; 2290 | /* LD SP,HL */ 2291 | case 0xf9: 2292 | sops = sops_add(sops, op_0("LD SP,HL")); 2293 | pc += 1; 2294 | break; 2295 | /* LD A,[a16] */ 2296 | case 0xfa: 2297 | addr16 = r->raw[phy(pc+1)] | (r->raw[phy(pc+2)]<<8); 2298 | sops = sops_add(sops, op_l16("LD A,[", addr16, "]")); 2299 | pc += 3; 2300 | break; 2301 | /* EI */ 2302 | case 0xfb: 2303 | sops = sops_add(sops, op_0("EI")); 2304 | pc += 1; 2305 | break; 2306 | /* CP d8 */ 2307 | case 0xfe: 2308 | addr8 = r->raw[phy(pc+1)]; 2309 | sops = sops_add(sops, op_r8("CP ", addr8)); 2310 | pc += 2; 2311 | break; 2312 | /* RST $38 */ 2313 | case 0xff: 2314 | sops = sops_add(sops, op_0("RST $38")); 2315 | pc += 1; 2316 | break; 2317 | /* AUTOGENERATED - end */ 2318 | --------------------------------------------------------------------------------