diff --git a/.gitignore b/.gitignore index 6f2ae84..5e826f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -nes +atari2600 +atari2600_debug +build/* diff --git a/lagueirtofile b/lagueirtofile index 589df46..ba06e7f 100644 --- a/lagueirtofile +++ b/lagueirtofile @@ -4,13 +4,15 @@ libs = -Wl,--gc-sections -lSDL3 executable = atari2600 sourcepath = source+ buildpath = build +exclude = z80* [linux_debug] default -cppflags = -D DEBUG -g -Wall -std=c++20 -Isource -libs = -lSDL3 -lGL +cppflags = -D DEBUG -g -std=c++20 -Isource +libs = -lSDL3 executable = atari2600_debug sourcepath = source+ buildpath = build +exclude = z80* [windows] cppflags = -Wall -Os -ffunction-sections -fdata-sections -std=c++20 -Isource diff --git a/6502m.cpp b/source/6502m.cpp similarity index 100% rename from 6502m.cpp rename to source/6502m.cpp diff --git a/6502m.h b/source/6502m.h similarity index 100% rename from 6502m.h rename to source/6502m.h diff --git a/atari2600.cpp b/source/atari2600.cpp similarity index 94% rename from atari2600.cpp rename to source/atari2600.cpp index 8ce4f93..7ea3a77 100644 --- a/atari2600.cpp +++ b/source/atari2600.cpp @@ -40,8 +40,8 @@ namespace atari2600 void step() { - uint8_t t_states; - uint16_t pc = m6502::getPC(); + //uint8_t t_states; + //uint16_t pc = m6502::getPC(); // if (z80debugger::isbreak(pc, 9)) { // msx::pause(); @@ -59,7 +59,7 @@ namespace atari2600 tia::tick(); tia::tick(); pia::tick(); - t_states++; + //t_states++; } //speaker::update(t_states); // } diff --git a/atari2600.h b/source/atari2600.h similarity index 100% rename from atari2600.h rename to source/atari2600.h diff --git a/source/display.cpp b/source/display.cpp new file mode 100644 index 0000000..3b8c889 --- /dev/null +++ b/source/display.cpp @@ -0,0 +1,251 @@ +#include "display.h" +#include +#include "tia.h" +#include "atari2600.h" +#include "ui_window.h" +//#include "z80debugger.h" +#include "ui.h" + +namespace display +{ + constexpr int screen_width = 160; + constexpr int screen_height = 192; + + // Standard Stella NTSC Palette (ARGB format: 0xFFRRGGBB) + // Indexed by: (COLUx >> 1) & 0x7F + const uint32_t palette[128] = { + // Hue $0 (Grayscale / Monochromatic) + 0xFF000000, 0xFF282828, 0xFF444444, 0xFF5C5C5C, 0xFF707070, 0xFF848484, 0xFF989898, 0xFFACACAC, + // Hue $1 (Gold / Yellow-Orange) + 0xFF4C2C00, 0xFF684400, 0xFF845C00, 0xFF9C7400, 0xFFB48C00, 0xFFCCA414, 0xFFE4BC34, 0xFFFCD454, + // Hue $2 (Orange / Red-Orange) + 0xFF541800, 0xFF742C00, 0xFF904400, 0xFFA85C00, 0xFFC07400, 0xFFD88C00, 0xFFF0A420, 0xFFFFBC40, + // Hue $3 (Red-Orange) + 0xFF580C00, 0xFF781C00, 0xFF943000, 0xFFB04800, 0xFFC86000, 0xFFE07808, 0xFFF89028, 0xFFFFA848, + // Hue $4 (Magenta / Red-Violet) + 0xFF540420, 0xFF74103C, 0xFF902058, 0xFFAC3474, 0xFFC4488C, 0xFFDC5CA8, 0xFFF474C0, 0xFFFF8CD8, + // Hue $5 (Purple / Violet) + 0xFF440454, 0xFF601074, 0xFF7C2090, 0xFF9434AC, 0xFFAC48C4, 0xFFC45CDC, 0xFFDC74F4, 0xFFF48CFF, + // Hue $6 (Blue-Violet / Indigo) + 0xFF2C0874, 0xFF441494, 0xFF5C24B0, 0xFF7438CC, 0xFF8C4CE4, 0xFFA460FC, 0xFFBC78FF, 0xFFD490FF, + // Hue $7 (Blue) + 0xFF101480, 0xFF2424A0, 0xFF3C38BC, 0xFF504CD4, 0xFF6860EC, 0xFF8078FF, 0xFF9890FF, 0xFFB0A8FF, + // Hue $8 (Blue-Cyan) + 0xFF002074, 0xFF003494, 0xFF0C48B0, 0xFF2060CC, 0xFF3474E4, 0xFF4C8CFC, 0xFF64A4FF, 0xFF7CBCFF, + // Hue $9 (Cyan / Blue-Green) + 0xFF002854, 0xFF004074, 0xFF005490, 0xFF006CAC, 0xFF1880C4, 0xFF3098DC, 0xFF48B0F4, 0xFF60C8FF, + // Hue $A (Teal / Green-Cyan) + 0xFF00302C, 0xFF004844, 0xFF00605C, 0xFF007874, 0xFF00908C, 0xFF1CA8A4, 0xFF38C0BC, 0xFF54D8D4, + // Hue $B (Green) + 0xFF003408, 0xFF004C18, 0xFF00642C, 0xFF007C40, 0xFF009454, 0xFF14AC6C, 0xFF30C484, 0xFF4CDC9C, + // Hue $C (Yellow-Green) + 0xFF0C3400, 0xFF204C00, 0xFF346400, 0xFF487C00, 0xFF5C9400, 0xFF74AC10, 0xFF8CC428, 0xFFA4DC44, + // Hue $D (Olive Green) + 0xFF243000, 0xFF3C4800, 0xFF546000, 0xFF6C7800, 0xFF849000, 0xFF9CA800, 0xFFB4C018, 0xFFCCC434, + // Hue $E (Brown / Olive-Yellow) + 0xFF3C2C00, 0xFF584000, 0xFF745800, 0xFF8C6C00, 0xFFA48400, 0xFFBC9C00, 0xFFD4B420, 0xFFECC83C, + // Hue $F (Orange-Brown) + 0xFF482400, 0xFF643800, 0xFF805000, 0xFF986400, 0xFFB07C00, 0xFFC89400, 0xFFE0AC28, 0xFFF8C444 + }; + + SDL_Window *win = nullptr; + SDL_Renderer *ren = nullptr; + SDL_Texture *tex = nullptr; + SDL_Texture *uitex = nullptr; + + uint8_t zoom = 1; + bool fullscreen = false; + int fullscreen_scale = 1; + SDL_FRect dest_rect; + + bool eventHandler(SDL_Event *e) + { + if (e->type==SDL_EVENT_WINDOW_CLOSE_REQUESTED) { + return false; + } else if ((e->type==SDL_EVENT_WINDOW_SHOWN) || (e->type==SDL_EVENT_WINDOW_EXPOSED)) { + redraw(); + } + if (e->type == SDL_EVENT_KEY_DOWN) { + const SDL_Scancode &key = e->key.scancode; + switch (key) { + case SDL_SCANCODE_F8: atari2600::pause(); /*z80debugger::show();*/ break; + case SDL_SCANCODE_F12: if (atari2600::is_paused()) atari2600::resume(); else atari2600::pause(); break; + case SDL_SCANCODE_Q: if (e->key.mod & SDL_KMOD_CTRL) { return false; break; } + default: break; + } + if (atari2600::is_paused()) { + switch (key) { + case SDL_SCANCODE_F2: display::decZoom(); break; + case SDL_SCANCODE_F3: display::incZoom(); break; + case SDL_SCANCODE_F4: display::toggleFullscreen(); break; + default: break; + } + } + } + if (e->type == SDL_EVENT_MOUSE_BUTTON_DOWN) { + if (atari2600::is_paused()) + atari2600::resume(); + else + atari2600::pause(); + } + if (e->type == SDL_EVENT_MOUSE_MOTION) { + SDL_ShowCursor(); + } + return true; + } + + void init() + { + if (win) ui::window::unregisterWindow(SDL_GetWindowID(win)); + + if (tex) SDL_DestroyTexture(tex); + if (uitex) SDL_DestroyTexture(uitex); + if (ren) SDL_DestroyRenderer(ren); + if (win) SDL_DestroyWindow(win); + + const int z = fullscreen ? 1 : zoom; + win = SDL_CreateWindow("Atari 2600 Screen", screen_width*2*z, screen_height*z, 0); + SDL_SetWindowFullscreen(win, fullscreen); + ren = SDL_CreateRenderer(win, NULL); + tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, screen_width, screen_height); + SDL_SetTextureScaleMode(tex, SDL_SCALEMODE_NEAREST); + uitex = ui::createtexture(ren); + + ui::window::registerWindow(SDL_GetWindowID(win), eventHandler); + + if (fullscreen) + { + int w, h; + SDL_GetWindowSize(win, &w, &h); + fullscreen_scale = h/screen_height; + dest_rect.w = screen_width*2 * fullscreen_scale; + dest_rect.h = screen_height * fullscreen_scale; + dest_rect.x = (w - dest_rect.w)/2; + dest_rect.y = (h - dest_rect.h)/2; + } + else + { + dest_rect.x = dest_rect.y = 0; + dest_rect.w = screen_width*2 * zoom; + dest_rect.h = screen_height * zoom; + } + + focus(); + } + + void focus() + { + if (win) + { + SDL_RaiseWindow(win); + redraw(); + } + } + + void redraw(const bool present) + { + //if (zx_tape::getplaying() && zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD)) return; + + //ui::setrenderer(ren, uitex); + + const uint8_t *framebuffer = tia::get_framebuffer(); + //framebuffer += screen_width*26; + Uint32* pixels; + int pitch; + SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch); + for (int i=0; i2 || fullscreen) { + // SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); + // SDL_SetRenderDrawColor(ren, 160, 170, 5, 96); + // const float scale = fullscreen ? fullscreen_scale : zoom; + // for (int i=0;i<144;++i) SDL_RenderDrawLine(ren, dest_rect.x, dest_rect.y+i*scale, dest_rect.x+159*scale, dest_rect.y+i*scale); + // for (int i=0;i<160;++i) SDL_RenderDrawLine(ren, dest_rect.x+i*scale, dest_rect.y, dest_rect.x+i*scale, dest_rect.y+143*scale); + //} + + //if (present) + // SDL_RenderPresent(ren); + //else + //{ + // SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); + // SDL_SetRenderDrawColor(ren, 0, 0, 0, 128); + // int w = screen_width*zoom; + // int h = screen_height*zoom; + // if (fullscreen) SDL_GetWindowSize(win, &w, &h); + // SDL_FRect rect {0,0,float(w),float(h)}; + // SDL_RenderFillRect(ren, &rect); + //} + + if (atari2600::is_paused()) { + SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(ren, 0, 0, 0, 128); + int w = screen_width*2*zoom; + int h = screen_height*zoom; + if (fullscreen) SDL_GetWindowSize(win, &w, &h); + SDL_FRect rect {0,0,float(w),float(h)}; + SDL_RenderFillRect(ren, &rect); + } + SDL_RenderPresent(ren); + } + + void present() + { + SDL_RenderPresent(ren); + } + + void setTitle(const char* title) + { + char tmp[256]; + strcpy(tmp, "MSX Screen"); + strcat(tmp, title); + SDL_SetWindowTitle(win, tmp); + } + + void setZoom(const int value) + { + if (fullscreen) return; + + if (value < 1) return; + const SDL_DisplayMode *dm = SDL_GetCurrentDisplayMode(SDL_GetDisplayForWindow(win)); + + if (screen_width*2*value > dm->w) return; + if (screen_height*value > dm->h) return; + + zoom = value; + init(); + } + + void incZoom() + { + if (fullscreen) return; + setZoom(zoom+1); + } + + void decZoom() + { + if (fullscreen) return; + setZoom(zoom-1); + } + + void toggleFullscreen() + { + fullscreen = !fullscreen; + init(); + } + + const bool getFullscreen() + { + return fullscreen; + } +} diff --git a/display.h b/source/display.h similarity index 100% rename from display.h rename to source/display.h diff --git a/source/main.cpp b/source/main.cpp new file mode 100644 index 0000000..dff6901 --- /dev/null +++ b/source/main.cpp @@ -0,0 +1,48 @@ +#include +#include "atari2600.h" +#include "rom.h" +#include "ui.h" +#include "ui_window.h" + +//#include "z80debugger.h" + +int main(int argc, char *argv[]) { + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); + + atari2600::init(); + + if (argc > 1) { + rom::load(argv[1]); + } else { + rom::load("combat.bin"); + } + + int wait = 16; + SDL_Event e; + while (!atari2600::is_quitting()) { + wait--; + if (wait==0) { + wait = 16; + if (atari2600::is_paused()) SDL_WaitEventTimeout(NULL, 1000); + while (SDL_PollEvent(&e)) { + bool result = true; + + if (e.type == SDL_EVENT_QUIT) { atari2600::quit(); break; } + if (e.type == SDL_EVENT_KEY_DOWN) { + if (atari2600::is_paused()) { + switch (e.key.scancode) { + case SDL_SCANCODE_F10: atari2600::step(); /*z80debugger::refresh();*/ break; + } + } + } + SDL_Window* window = SDL_GetWindowFromEvent(&e); + if (!ui::window::sendEvent(SDL_GetWindowID(window), &e)) { atari2600::quit(); break; } + } + } + if (!atari2600::is_paused()) atari2600::step(); + ui::setClicked(false); + } + + SDL_Quit(); + return 0; +} \ No newline at end of file diff --git a/mem.cpp b/source/mem.cpp similarity index 100% rename from mem.cpp rename to source/mem.cpp diff --git a/mem.h b/source/mem.h similarity index 100% rename from mem.h rename to source/mem.h diff --git a/pia.cpp b/source/pia.cpp similarity index 80% rename from pia.cpp rename to source/pia.cpp index 3385f66..2584dce 100644 --- a/pia.cpp +++ b/source/pia.cpp @@ -32,9 +32,15 @@ namespace pia // I/O Ports switch( address & 0x03) { case 0x00: // [TODO] SWCHA + return 0x00; case 0x01: // [TODO] DDRA + return 0x00; case 0x02: // [TODO] SWCHB + return 0x00; case 0x03: // [TODO] DDRB + return 0x00; + default: + return 0x00; } } } else { @@ -50,9 +56,13 @@ namespace pia // Timer functions switch( address & 0x03) { case 0x00: // [TODO] TIM1T + break; case 0x01: // [TODO] TIM8T + break; case 0x02: // [TODO] TIM64T + break; case 0x03: // [TODO] TIM1024T + break; } } else { // Funcionalitat relacionada amb les interrupcions. Ignorar per a la Atari 2600 @@ -61,9 +71,13 @@ namespace pia // I/O Ports switch( address & 0x03) { case 0x00: // [TODO] SWCHA + break; case 0x01: // [TODO] DDRA + break; case 0x02: // [TODO] SWCHB + break; case 0x03: // [TODO] DDRB + break; } } } else { diff --git a/pia.h b/source/pia.h similarity index 100% rename from pia.h rename to source/pia.h diff --git a/rom.cpp b/source/rom.cpp similarity index 100% rename from rom.cpp rename to source/rom.cpp diff --git a/rom.h b/source/rom.h similarity index 100% rename from rom.h rename to source/rom.h diff --git a/speaker.cpp b/source/speaker.cpp similarity index 100% rename from speaker.cpp rename to source/speaker.cpp diff --git a/speaker.h b/source/speaker.h similarity index 100% rename from speaker.h rename to source/speaker.h diff --git a/tia-audio.cpp b/source/tia-audio.cpp similarity index 100% rename from tia-audio.cpp rename to source/tia-audio.cpp diff --git a/tia-audio.h b/source/tia-audio.h similarity index 100% rename from tia-audio.h rename to source/tia-audio.h diff --git a/tia.cpp b/source/tia.cpp similarity index 60% rename from tia.cpp rename to source/tia.cpp index 123b32e..06e0ea6 100644 --- a/tia.cpp +++ b/source/tia.cpp @@ -1,46 +1,24 @@ #include "tia.h" #include "tia-audio.h" +#include "display.h" namespace tia { - // Standard Stella NTSC Palette (ARGB format: 0xFFRRGGBB) - // Indexed by: (COLUx >> 1) & 0x7F - const uint32_t NTSC_PALETTE[128] = { - // Hue $0 (Grayscale / Monochromatic) - 0xFF000000, 0xFF282828, 0xFF444444, 0xFF5C5C5C, 0xFF707070, 0xFF848484, 0xFF989898, 0xFFACACAC, - // Hue $1 (Gold / Yellow-Orange) - 0xFF4C2C00, 0xFF684400, 0xFF845C00, 0xFF9C7400, 0xFFB48C00, 0xFFCCA414, 0xFFE4BC34, 0xFFFCD454, - // Hue $2 (Orange / Red-Orange) - 0xFF541800, 0xFF742C00, 0xFF904400, 0xFFA85C00, 0xFFC07400, 0xFFD88C00, 0xFFF0A420, 0xFFFFBC40, - // Hue $3 (Red-Orange) - 0xFF580C00, 0xFF781C00, 0xFF943000, 0xFFB04800, 0xFFC86000, 0xFFE07808, 0xFFF89028, 0xFFFFA848, - // Hue $4 (Magenta / Red-Violet) - 0xFF540420, 0xFF74103C, 0xFF902058, 0xFFAC3474, 0xFFC4488C, 0xFFDC5CA8, 0xFFF474C0, 0xFFFF8CD8, - // Hue $5 (Purple / Violet) - 0xFF440454, 0xFF601074, 0xFF7C2090, 0xFF9434AC, 0xFFAC48C4, 0xFFC45CDC, 0xFFDC74F4, 0xFFF48CFF, - // Hue $6 (Blue-Violet / Indigo) - 0xFF2C0874, 0xFF441494, 0xFF5C24B0, 0xFF7438CC, 0xFF8C4CE4, 0xFFA460FC, 0xFFBC78FF, 0xFFD490FF, - // Hue $7 (Blue) - 0xFF101480, 0xFF2424A0, 0xFF3C38BC, 0xFF504CD4, 0xFF6860EC, 0xFF8078FF, 0xFF9890FF, 0xFFB0A8FF, - // Hue $8 (Blue-Cyan) - 0xFF002074, 0xFF003494, 0xFF0C48B0, 0xFF2060CC, 0xFF3474E4, 0xFF4C8CFC, 0xFF64A4FF, 0xFF7CBCFF, - // Hue $9 (Cyan / Blue-Green) - 0xFF002854, 0xFF004074, 0xFF005490, 0xFF006CAC, 0xFF1880C4, 0xFF3098DC, 0xFF48B0F4, 0xFF60C8FF, - // Hue $A (Teal / Green-Cyan) - 0xFF00302C, 0xFF004844, 0xFF00605C, 0xFF007874, 0xFF00908C, 0xFF1CA8A4, 0xFF38C0BC, 0xFF54D8D4, - // Hue $B (Green) - 0xFF003408, 0xFF004C18, 0xFF00642C, 0xFF007C40, 0xFF009454, 0xFF14AC6C, 0xFF30C484, 0xFF4CDC9C, - // Hue $C (Yellow-Green) - 0xFF0C3400, 0xFF204C00, 0xFF346400, 0xFF487C00, 0xFF5C9400, 0xFF74AC10, 0xFF8CC428, 0xFFA4DC44, - // Hue $D (Olive Green) - 0xFF243000, 0xFF3C4800, 0xFF546000, 0xFF6C7800, 0xFF849000, 0xFF9CA800, 0xFFB4C018, 0xFFCCC434, - // Hue $E (Brown / Olive-Yellow) - 0xFF3C2C00, 0xFF584000, 0xFF745800, 0xFF8C6C00, 0xFFA48400, 0xFFBC9C00, 0xFFD4B420, 0xFFECC83C, - // Hue $F (Orange-Brown) - 0xFF482400, 0xFF643800, 0xFF805000, 0xFF986400, 0xFFB07C00, 0xFFC89400, 0xFFE0AC28, 0xFFF8C444 - }; - - uint8_t collisions[8] { 0, 0, 0, 0, 0, 0, 0, 0 }; + bool collision_missile0_player1 = false; + bool collision_missile0_player0 = false; + bool collision_missile1_player0 = false; + bool collision_missile1_player1 = false; + bool collision_player0_playfield = false; + bool collision_player0_ball = false; + bool collision_player1_playfield = false; + bool collision_player1_ball = false; + bool collision_missile0_playfield = false; + bool collision_missile0_ball = false; + bool collision_missile1_playfield = false; + bool collision_missile1_ball = false; + bool collision_ball_playfield = false; + bool collision_player0_player1 = false; + bool collision_missile0_missile1 = false; float paddle_pos[4] { 0.5f, 0.5f, 0.5f, 0.5f }; uint32_t paddle_charge_cycles[4] { 0, 0, 0, 0 }; @@ -51,7 +29,7 @@ namespace tia uint8_t player0_size = 1; uint8_t player0_num_copies = 1; uint8_t player0_copies_distance = 0; - uint32_t player0_color = 0x00000000; + uint8_t player0_color = 0; bool player0_reflect = false; uint8_t player0_pos = 0; uint8_t player0_bits = 0; @@ -63,7 +41,7 @@ namespace tia uint8_t player1_size = 1; uint8_t player1_num_copies = 1; uint8_t player1_copies_distance = 0; - uint32_t player1_color = 0x00000000; + uint8_t player1_color = 0; bool player1_reflect = false; uint8_t player1_pos = 0; uint8_t player1_bits = 0; @@ -94,7 +72,7 @@ namespace tia bool ball_vert_delay = false; uint8_t ball_pixel_counter = 0; - uint32_t playfield_color = 0x00000000; + uint8_t playfield_color = 0; bool playfield_reflected = false; bool playfield_score = false; bool playfield_priority = false; @@ -106,7 +84,7 @@ namespace tia {16,17,18,19, 15,14,13,12,11,10,9,8, 0,1,2,3,4,5,6,7, 7,6,5,4,3,2,1,0, 8,9,10,11,12,13,14,15, 19,18,17,16} }; - uint32_t background_color = 0x00000000; + uint8_t background_color = 0; uint32_t current_frame_cycles = 0; @@ -121,11 +99,18 @@ namespace tia uint16_t current_scanline = 0; bool rdy_low = false; + uint8_t framebuffer[160][192]; + void reset() { } + const uint8_t *get_framebuffer() + { + return (const uint8_t*)framebuffer; + } + void tick() { if (!vblank_dump) current_frame_cycles++; @@ -164,6 +149,96 @@ namespace tia ball_pixel_counter = ball_size; } + bool player0_visible = false; + bool player1_visible = false; + bool missile0_visible = false; + bool missile1_visible = false; + bool ball_visible = false; + bool playfield_visible = false; + + if (player0_pixel_counter>0) { + if ((player0_bits>>player0_pixel_position)&0x01) player0_visible = true; + player0_pixel_counter--; + if ( (player0_pixel_counter==0) && (player0_pixel_position>0) ) { + player0_pixel_counter = player0_size; + player0_pixel_position--; + } + } + + if (player1_pixel_counter>0) { + if ((player1_bits>>player1_pixel_position)&0x01) player1_visible = true; + player1_pixel_counter--; + if ( (player1_pixel_counter==0) && (player1_pixel_position>0) ) { + player1_pixel_counter = player1_size; + player1_pixel_position--; + } + } + + if (missile0_pixel_counter>0) { + missile0_visible = true; + missile0_pixel_counter--; + } + + if (missile1_pixel_counter>0) { + missile1_visible = true; + missile1_pixel_counter--; + } + + if (ball_pixel_counter>0) { + ball_visible = true; + ball_pixel_counter--; + } + + const uint8_t playfield_clock = pixel_clock >> 2; + const uint8_t playfield_shift = playfield_shifts[playfield_reflected?1:0][playfield_clock]; + if ( (playfield_bits >> playfield_shift) & 0x01) { + playfield_visible = true; + } + + if (missile0_visible && player1_visible) collision_missile0_player1 = true; + if (missile0_visible && player0_visible) collision_missile0_player0 = true; + if (missile1_visible && player0_visible) collision_missile1_player0 = true; + if (missile1_visible && player1_visible) collision_missile1_player1 = true; + if (player0_visible && playfield_visible) collision_player0_playfield = true; + if (player0_visible && ball_visible) collision_player0_ball = true; + if (player1_visible && playfield_visible) collision_player1_playfield = true; + if (player1_visible && ball_visible) collision_player1_ball = true; + if (missile0_visible && playfield_visible) collision_missile0_playfield = true; + if (missile0_visible && ball_visible) collision_missile0_ball = true; + if (missile1_visible && playfield_visible) collision_missile1_playfield = true; + if (missile1_visible && ball_visible) collision_missile1_ball = true; + if (ball_visible && playfield_visible) collision_ball_playfield = true; + if (player0_visible && player1_visible) collision_player0_player1 = true; + if (missile0_visible && missile1_visible) collision_missile0_missile1 = true; + + const uint8_t x = pixel_clock; + const uint8_t y = current_scanline-37; + + if (playfield_priority) { + if (ball_visible) { + framebuffer[y][x] = playfield_color; + } else if (playfield_visible) { + framebuffer[y][x] = playfield_score ? (x<80 ? player0_color : player1_color) : playfield_color; + } else if (player0_visible || missile0_visible) { + framebuffer[y][x] = player0_color; + } else if (player1_visible || missile1_visible) { + framebuffer[y][x] = player1_color; + } else { + framebuffer[y][x] = background_color; + } + } else { + if (player0_visible || missile0_visible) { + framebuffer[y][x] = player0_color; + } else if (player1_visible || missile1_visible) { + framebuffer[y][x] = player1_color; + } else if (ball_visible) { + framebuffer[y][x] = playfield_color; + } else if (playfield_visible) { + framebuffer[y][x] = playfield_score ? (x<80 ? player0_color : player1_color) : playfield_color; + } else { + framebuffer[y][x] = background_color; + } + } } } @@ -178,14 +253,14 @@ namespace tia uint8_t read(uint16_t address) { switch (address & 0x0f) { - case 0x00: return collisions[0]; - case 0x01: return collisions[1]; - case 0x02: return collisions[2]; - case 0x03: return collisions[3]; - case 0x04: return collisions[4]; - case 0x05: return collisions[5]; - case 0x06: return collisions[6]; - case 0x07: return collisions[7]; + case 0x00: return (collision_missile0_player1?0x80:0x00) | (collision_missile0_player0?0x40:0x00); + case 0x01: return (collision_missile1_player0?0x80:0x00) | (collision_missile1_player1?0x40:0x00); + case 0x02: return (collision_player0_playfield?0x80:0x00) | (collision_player0_ball?0x40:0x00); + case 0x03: return (collision_player1_playfield?0x80:0x00) | (collision_player1_ball?0x40:0x00); + case 0x04: return (collision_missile0_playfield?0x80:0x00) | (collision_missile0_ball?0x40:0x00); + case 0x05: return (collision_missile1_playfield?0x80:0x00) | (collision_missile1_ball?0x40:0x00); + case 0x06: return (collision_ball_playfield?0x80:0x00); + case 0x07: return (collision_player0_player1?0x80:0x00) | (collision_missile0_missile1?0x40:0x00); case 0x08: return get_paddle_state(0); case 0x09: return get_paddle_state(1); @@ -194,6 +269,7 @@ namespace tia case 0x0C: return joy0_button_pressed ? 0x00 : 0x80; case 0x0D: return joy1_button_pressed ? 0x00 : 0x80; + default: return 0x00; } } @@ -205,14 +281,17 @@ namespace tia // [TODO] Procesar segons l'adreça resultant switch (address) { case 0x00: // VSYNC + { const bool old_vsync = vsync_set; vsync_set = value & 0x20; if (old_vsync && !vsync_set) { // Resetejem el frame current_scanline = 0; + display::redraw(); } break; - + } case 0x01: // VBLANK + { bool prev_dump = vblank_dump; vblank_set = value & 0x20; vblank_latch = value & 0x40; @@ -220,9 +299,10 @@ namespace tia if (prev_dump && !vblank_dump) { current_frame_cycles = 0; for (int i = 0; i < 4; ++i) paddle_charge_cycles[i] = static_cast(paddle_pos[i] * 2400.0f); + } break; - + } case 0x02: // WSYNC rdy_low = true; break; @@ -232,7 +312,7 @@ namespace tia rdy_low = false; break; - case 0x004: // NUSIZ0 + case 0x04: // NUSIZ0 missile0_size = 1 << ((value >> 4) & 0x03); switch (value & 0x07) { case 0: player0_num_copies = 1; player0_copies_distance = 0; player0_size = 1; break; @@ -246,7 +326,7 @@ namespace tia } break; - case 0x005: // NUSIZ1 + case 0x05: // NUSIZ1 missile1_size = 1 << ((value >> 4) & 0x03); switch (value & 0x07) { case 0: player1_num_copies = 1; player1_copies_distance = 0; player1_size = 1; break; @@ -261,13 +341,13 @@ namespace tia break; case 0x06: // COLUP0 - player0_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break; + player0_color = (value >> 1) & 0x7F; break; case 0x07: // COLUP1 - player1_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break; + player1_color = (value >> 1) & 0x7F; break; case 0x08: // COLUPF - playfield_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break; + playfield_color = (value >> 1) & 0x7F; break; case 0x09: // COLUBK - background_color = NTSC_PALETTE[(value >> 1) & 0x7F]; break; + background_color = (value >> 1) & 0x7F; break; case 0x0A: // CTRLPF playfield_reflected = value & 0x01; @@ -357,7 +437,21 @@ namespace tia player0_hmotion = player1_hmotion = missile0_hmotion = missile1_hmotion = ball_hmotion = 0; break; case 0x2C: // CXCLR - for (int i=0;i<8;++i) collisions[i] = 0; + collision_missile0_player1 = false; + collision_missile0_player0 = false; + collision_missile1_player0 = false; + collision_missile1_player1 = false; + collision_player0_playfield = false; + collision_player0_ball = false; + collision_player1_playfield = false; + collision_player1_ball = false; + collision_missile0_playfield = false; + collision_missile0_ball = false; + collision_missile1_playfield = false; + collision_missile1_ball = false; + collision_ball_playfield = false; + collision_player0_player1 = false; + collision_missile0_missile1 = false; break; } } diff --git a/tia.h b/source/tia.h similarity index 88% rename from tia.h rename to source/tia.h index 6973e1d..2e3cae8 100644 --- a/tia.h +++ b/source/tia.h @@ -10,6 +10,8 @@ namespace tia bool is_rdy_low(); + const uint8_t *get_framebuffer(); + namespace audio { uint8_t get_sample0(); diff --git a/source/ui.cpp b/source/ui.cpp new file mode 100644 index 0000000..5f8ee4f --- /dev/null +++ b/source/ui.cpp @@ -0,0 +1,172 @@ +#include "ui.h" + +namespace ui +{ + uint8_t colors[16][3] = { + {0,0,0}, + {0,0,128}, + {0,128,0}, + {0,128,128}, + {128,0,0}, + {128,0,128}, + {255,128,0}, + {128,128,128}, + {30,30,30}, + {0,0,255}, + {0,255,0}, + {0,255,255}, + {255,0,0}, + {255,0,255}, + {255,255,0}, + {255,255,255}, + }; + + SDL_Renderer *ren = nullptr; + SDL_Texture *tex = nullptr; + + uint8_t offset_x = 0; + uint8_t offset_y = 0; + + bool clicked = false; + + void (*dialog)(void) = nullptr; + + SDL_Texture * createtexture(SDL_Renderer *renderer) + { + SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, SDL_LoadBMP("font.bmp")); + SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST); + SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); + return texture; + } + + void setrenderer(SDL_Renderer *renderer, SDL_Texture *texture) + { + ren = renderer; + tex = texture; + offset_x = offset_y = 0; + } + + void setoffset(uint8_t x, uint8_t y) + { + offset_x = x; + offset_y = y; + } + + void incoffset(uint8_t x, uint8_t y) + { + offset_x += x; + offset_y += y; + } + + uint8_t getOffsetX() + { + return offset_x; + } + + uint8_t getOffsetY() + { + return offset_y; + } + + bool mouseInside(int x, int y, int w, int h) + { + float mxf, myf; + SDL_GetMouseState(&mxf, &myf); + int mx = int(mxf)/CHR_W; + int my = int(myf)/CHR_H; + mx -= offset_x; + my -= offset_y; + return (mx >= x) && (mx < x+w) && (my >= y) && (my < y+h); + } + + void panel(int x, int y, int w, int h, const char *title) + { + ui::setoffset(x, y); + + ui::box(0,0,w,h,COLOR_WHITE); + ui::printrect(2,0, strlen(title)+2,1, COLOR_DARK); + ui::printtxt(3,0, title, COLOR_WHITE); + + ui::incoffset(1, 1); + } + + void box(int x, int y, int w, int h, uint8_t color) + { + SDL_FRect rect {float((offset_x+x)*CHR_W)+3, float((offset_y+y)*CHR_H)+6, float(w*CHR_W-6), float(h*CHR_H-13)}; + SDL_SetRenderDrawColor(ren, colors[color][0], colors[color][1], colors[color][2], 255); + SDL_RenderRect(ren, &rect); + } + + void printrect(int x, int y, int w, int h, uint8_t color) + { + SDL_FRect rect {float(offset_x+x)*CHR_W, float(offset_y+y)*CHR_H, float(w*CHR_W), float(h*CHR_H)}; + SDL_SetRenderDrawColor(ren, colors[color][0], colors[color][1], colors[color][2], 255); + SDL_RenderFillRect(ren, &rect); + } + + void printvoidrect(int x, int y, int w, int h, uint8_t color) + { + SDL_FRect rect {float(offset_x+x)*CHR_W, float(offset_y+y)*CHR_H, float(w*CHR_W), float(h*CHR_H)}; + SDL_SetRenderDrawColor(ren, colors[color][0], colors[color][1], colors[color][2], 255); + SDL_RenderRect(ren, &rect); + } + + void printchar(int x, int y, char chr, uint8_t color) + { + if (color != 255) SDL_SetRenderDrawColor(ren, colors[color][0], colors[color][1], colors[color][2], 255); + if (chr==32) return; + if (chr<32 || chr>127) chr = '.'; + SDL_FRect src {float((chr-32)&0xf)*CHR_W, float((chr-32)>>4)*CHR_H, float(CHR_W), float(CHR_H)}; + SDL_FRect dst {float(offset_x+x)*CHR_W, float(offset_y+y)*CHR_H, float(CHR_W), float(CHR_H)}; + SDL_RenderTexture(ren, tex, &src, &dst); + } + + void printtxt(int x, int y, const char *text, uint8_t color) + { + SDL_SetTextureColorMod(tex, colors[color][0], colors[color][1], colors[color][2]); + for (int i=0; i127) chr = '.'; + SDL_FRect src {float((chr-32)&0xf)*CHR_W, float((chr-32)>>4)*CHR_H, float(CHR_W), float(CHR_H)}; + SDL_FRect dst {float(x), float(y), float(CHR_W*2), float(CHR_H*2)}; + SDL_RenderTexture(ren, tex, &src, &dst); + } + + void placetxt(int x, int y, const char *text, uint8_t color) + { + SDL_SetTextureColorMod(tex, colors[color][0], colors[color][1], colors[color][2]); + for (int i=0; i + +namespace ui +{ + #define CHR_W 6 + #define CHR_H 13 + + #define COLOR_BLACK 0 + #define COLOR_DARK_BLUE 1 + #define COLOR_GREEN 2 + #define COLOR_TEAL 3 + #define COLOR_BROWN 4 + #define COLOR_PURPLE 5 + #define COLOR_ORANGE 6 + #define COLOR_GRAY 7 + #define COLOR_DARK 8 + #define COLOR_BLUE 9 + #define COLOR_LIME 10 + #define COLOR_CYAN 11 + #define COLOR_RED 12 + #define COLOR_MAGENTA 13 + #define COLOR_YELLOW 14 + #define COLOR_WHITE 15 + + SDL_Texture * createtexture(SDL_Renderer *renderer); + void setrenderer(SDL_Renderer *renderer, SDL_Texture *texture); + void setoffset(uint8_t x, uint8_t y); + void incoffset(uint8_t x, uint8_t y); + uint8_t getOffsetX(); + uint8_t getOffsetY(); + bool mouseInside(int x, int y, int w, int h); + + void panel(int x, int y, int w, int h, const char *title); + void box(int x, int y, int w, int h, uint8_t color); + void printrect(int x, int y, int w, int h, uint8_t color); + void printvoidrect(int x, int y, int w, int h, uint8_t color); + void printchar(int x, int y, char chr, uint8_t color=255); + void printtxt(int x, int y, const char *text, uint8_t color); + + void placechar(int x, int y, char chr, uint8_t color=255); + void placetxt(int x, int y, const char *text, uint8_t color); + + void setClicked(const bool value); + const bool getClicked(); + + void setDialog(void(*new_dialog)(void)); + bool hasDialog(); + void callDialog(); +} diff --git a/source/ui_window.cpp b/source/ui_window.cpp new file mode 100644 index 0000000..b943c52 --- /dev/null +++ b/source/ui_window.cpp @@ -0,0 +1,33 @@ +#include "ui_window.h" +#include + +namespace ui +{ + namespace window + { + struct window_t + { + Uint32 window; + bool (*callback)(SDL_Event*); + }; + std::vector windows; + + void registerWindow(Uint32 window, bool(*callback)(SDL_Event*)) + { + for (auto win : windows) if (win.window == window) return; + windows.push_back((window_t){window, callback}); + } + + void unregisterWindow(Uint32 window) + { + for (auto win = windows.begin(); win != windows.end(); win++) if ((*win).window == window) { windows.erase(win); return; } + } + + bool sendEvent(Uint32 window, SDL_Event *e) + { + for (auto win : windows) if (win.window == window) return win.callback(e); + return true; + } + + } +} diff --git a/source/ui_window.h b/source/ui_window.h new file mode 100644 index 0000000..a6b4f03 --- /dev/null +++ b/source/ui_window.h @@ -0,0 +1,12 @@ +#pragma once +#include + +namespace ui +{ + namespace window + { + void registerWindow(Uint32 window, bool(*callback)(SDL_Event *e)); + void unregisterWindow(Uint32 window); + bool sendEvent(Uint32 window, SDL_Event *e); + } +} diff --git a/z80debugger.cpp b/z80debugger.cpp new file mode 100644 index 0000000..688eb32 --- /dev/null +++ b/z80debugger.cpp @@ -0,0 +1,1212 @@ +#include "z80debugger.h" +#include +#include +#include "msx.h" +#include "mem.h" +#include "z80.h" +#include "z80dis.h" +#include "display.h" +#include "ui.h" +#include "ui_window.h" +#include "cassette.h" + +#define RESIZING_NONE 0 +#define RESIZING_MEMORY 1 +#define RESIZING_CONSOLE 2 +#define RESIZING_SYMBOLS 3 +#define RESIZING_X 4 + +namespace z80debugger +{ + int midx = 58; + int mem_y = 20; + int con_y = 28; + int sym_y = 24; + int win_h = 44; + int mem_h = 8; + int con_h = 6; + int sym_h = 14; + uint8_t tags[65536]; + int resizing_type = RESIZING_MEMORY; + bool resizing = false; + + namespace history + { + uint16_t buffer[65536]; + uint8_t top=0; + uint8_t pos=0; + } + + uint16_t oAF, oBC, oDE, oHL, oAF2, oBC2, oDE2, oHL2, oIX, oIY, oSP, oPC; + uint8_t oI, oR; + + bool mem_modified[65536]; //[CHECK] + + SDL_Window *win = nullptr; + SDL_Renderer *ren = nullptr; + SDL_Texture *tex = nullptr; + SDL_Cursor *cur_df = nullptr; + SDL_Cursor *cur_ns = nullptr; + SDL_Cursor *cur_we = nullptr; + + uint16_t mem_viewer_pos = 0; + + char console_log[256][256]; + char console_history[256][256]; + uint8_t console_log_pos = 255; + uint8_t console_history_pos = 0; + uint8_t console_history_nav = 0; + + uint8_t breakpoints[65536]; + + uint16_t cursor = 0; + + uint8_t use[7][256]; + + uint16_t line_address[256]; + uint16_t line_breakpoint_address[256]; + int num_breakpoint_lines=0; + bool sync_mem_with_cursor = false; + + uint8_t search_sequence[32]; + int search_sequence_len=0; + int search_pos=0; + + uint16_t inspected_value = 255; + + char temp[256]; + const char *tohex(int value, int numdigits) + { + if (numdigits==2) sprintf(temp, "%02X", value); + else if (numdigits==4) sprintf(temp, "%04X", value); + return temp; + } + const char *todec(int value, bool sign) + { + if (sign) + sprintf(temp, "%i", int8_t(value)); + else + sprintf(temp, "%u", value); + return temp; + } + + bool eventHandler(SDL_Event *e) + { + if (e->type == SDL_EVENT_MOUSE_MOTION) { + SDL_ShowCursor(); + } + if (msx::is_paused()) { + if ((e->type==SDL_EVENT_WINDOW_SHOWN) || (e->type==SDL_EVENT_WINDOW_EXPOSED)) { + int w; int h; + SDL_GetWindowSize(win, &w, &h); + midx = (w/CHR_W) - 25; + win_h = (h/CHR_H); + mem_y = win_h - mem_h - con_h; + con_y = win_h - con_h; + sym_h = win_h - sym_y; + refresh(); + } else if (e->type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) { + hide(); + //zxscreen::focus(); + } + if (e->type == SDL_EVENT_MOUSE_WHEEL) { + if (e->wheel.mouse_xwheel.mouse_ywheel.y>0) { + cursorback(); + refresh(); + } else if (e->wheel.y<0) { + cursorfwd(); + refresh(); + } + } else if (e->wheel.mouse_xwheel.mouse_y>=mem_y*CHR_H && e->wheel.mouse_ywheel.y>0) { + mem_viewer_pos-=0x10; + refresh(); + } else if (e->wheel.y<0) { + mem_viewer_pos+=0x10; + refresh(); + } + } + } + if (e->type == SDL_EVENT_KEY_DOWN) { + if (e->key.scancode==SDL_SCANCODE_ESCAPE) { + return false; + } else if (e->key.scancode==SDL_SCANCODE_F1) { + history::gototop(); + refresh(); + } else if (e->key.scancode==SDL_SCANCODE_F2) { + history::goback(); + refresh(); + } else if (e->key.scancode==SDL_SCANCODE_F3) { + history::goforward(); + refresh(); + } else if (e->key.scancode==SDL_SCANCODE_F9) { + const uint16_t address = cursor; + if (breakpoints[line_address[address]]==0) + breakpoints[line_address[address]]=1; + else + breakpoints[line_address[address]]=0; + refresh(); + } else if (e->key.scancode==SDL_SCANCODE_UP) { + if (console_history_nav != console_history_pos+1 && console_history[console_history_nav-1][0]!=0) console_history_nav--; + //z80debug::cursorback(); + refresh(); + } else if (e->key.scancode==SDL_SCANCODE_DOWN) { + if (console_history_nav != console_history_pos) console_history_nav++; + //z80debug::cursorfwd(); + refresh(); + } else if ( (e->key.scancode==SDL_SCANCODE_RETURN) || (e->key.scancode==SDL_SCANCODE_KP_ENTER)) { + executeConsole(); + } else if (e->key.scancode==SDL_SCANCODE_BACKSPACE) { + DeleteCharConsole(); + } + } + if (e->type == SDL_EVENT_MOUSE_MOTION) { + if (!resizing) { + if ( (e->motion.y > (mem_y*CHR_H)-8) && (e->motion.y < (mem_y*CHR_H)+8) && ( e->motion.x < midx*CHR_W ) ) { + if (resizing_type != RESIZING_MEMORY) SDL_SetCursor(cur_ns); + resizing_type = RESIZING_MEMORY; + } else if ( (e->motion.y > (sym_y*CHR_H)-8) && (e->motion.y < (sym_y*CHR_H)+8) && ( e->motion.x >= midx*CHR_W ) ) { + if (resizing_type != RESIZING_SYMBOLS) SDL_SetCursor(cur_ns); + resizing_type = RESIZING_SYMBOLS; + } else if ( (e->motion.y > (con_y*CHR_H)-8) && (e->motion.y < (con_y*CHR_H)+8) && (e->motion.x < midx*CHR_W) ) { + if (resizing_type != RESIZING_CONSOLE) SDL_SetCursor(cur_ns); + resizing_type = RESIZING_CONSOLE; + } else { + if (resizing_type != RESIZING_NONE) SDL_SetCursor(cur_df); + resizing_type = RESIZING_NONE; + } + + const int chrx = e->motion.x/CHR_W; + const int chry = e->motion.y/CHR_H; + //printf("%ix%i\n", chrx, chry); + // Si pasa per damunt de l'adreça en el desensamblador + if ( (chrx>1) && (chrx<6) && (chry0) ) { + inspected_value = line_address[chry-1]; + refresh(); + // Si pasa per damunt dels bytes que formen el opcode en el desensamblador + } else if ((chrx>=19) && (chrx<30) && (chry0)) { + const uint16_t address = line_address[chry-1]; + const int opcodesize = z80dis::getOpcodeSize(address); + const int byte = (chrx-19)/3; + if (byte < opcodesize) { + inspected_value = mem::read(address+byte); + refresh(); + } + // Si pasa per damunt de l'adreça en el visor de memòria + } else if ((chrx>1) && (chrx<6) && (chry>mem_y) && (chry6) && (chrx<55) && (chry>mem_y) && (chry=midx+4) && (chrx=midx+4) && (chrx=midx+4) && (chrx=midx+4) && (chrx=midx+12) && (chrx=midx+12) && (chrx=midx+12) && (chrx=midx+12) && (chrx=midx+20) && (chrx=midx+20) && (chrx=midx+20) && (chrx=midx+20) && (chrx=midx+6) && (chrx=midx+14) && (chrx=midx+22) && (chrx=midx+17) && (chrx=midx+22) && (chrxmotion.y/CHR_H; + const int new_mem_h = win_h - new_mem_y - con_h; + if (new_mem_y>=5 && new_mem_h>=3) { + mem_y = new_mem_y; + mem_h = new_mem_h; + refresh(); + } + } else if (resizing_type==RESIZING_CONSOLE) { + const int new_con_y = e->motion.y/CHR_H; + const int new_con_h = win_h - new_con_y; + const int new_mem_y = win_h - mem_h - new_con_h; + if (new_mem_y>=5 && new_con_h>=3) { + mem_y = new_mem_y; + con_y = new_con_y; + con_h = new_con_h; + refresh(); + } + } else if (resizing_type==RESIZING_SYMBOLS) { + const int new_sym_y = e->motion.y/CHR_H; + const int new_sym_h = win_h - new_sym_y; + if (new_sym_y>=12 && new_sym_h >=3) { + sym_y = new_sym_y; + sym_h = new_sym_h; + refresh(); + } + } + } + } + if (e->type == SDL_EVENT_MOUSE_BUTTON_DOWN) { + const int chrx = e->button.x/CHR_W; + const int chry = e->button.y/CHR_H; + //printf("%ix%i\n", chrx, chry); + if ( (e->button.xbutton.y<(mem_y-1)*CHR_H) && (e->button.y>CHR_H) ) { + const uint16_t address = ((e->button.y)/CHR_H)-1; + if (breakpoints[line_address[address]]==0) + breakpoints[line_address[address]]=1; + else + breakpoints[line_address[address]]=0; + refresh(); + } + if (chrx>=midx+12 && chry>=9 && chrybreakpoint_selected) { + cursor = line_breakpoint_address[breakpoint_selected]; + refresh(); + } + } + + if (chrx>=10 && chrx<=12 && chry==mem_y) { + sync_mem_with_cursor = ! sync_mem_with_cursor; + refresh(); + } + + if (chrx>=midx+2 && chry>=sym_y+1) { + const int line = chry-(sym_y+1); + if (linetype == SDL_EVENT_MOUSE_BUTTON_UP) { + if (resizing) { + resizing = false; + } + } + if (e->type == SDL_EVENT_TEXT_INPUT) { + sendToConsole(e->text.text); + } + } + return true; + } + + void processCommand(); + + + uint8_t getTag(uint16_t address) + { + return tags[address]; + } + + void setTag(uint16_t address, uint8_t value) + { + tags[address] = value; + } + + void onInstructionExecute(uint16_t address) + { + uint8_t &tag = tags[address]; + if ( !(tag & MEMTAG_IGNORE) ) tag |= MEMTAG_INST; + tag |= (!(tag&MEMTAG_TOUCHED) ? MEMTAG_TREPEAT : MEMTAG_TINST); + + setcursor(z80::getPC()); + history::store(); + } + + void onMemRead(uint16_t address, bool code) + { + if (isbreak(address, 2)) stop(); + + uint8_t &tag = tags[address]; + if ( tag & MEMTAG_IGNORE) return; + + if ( code ) { + tag |= MEMTAG_CODE; + } else if ( !(tag & MEMTAG_INST) ) { + tag |= MEMTAG_DATA; + } + } + + void onMemWrite(uint16_t address) + { + if (isbreak(address, 4)) stop(); + + mem_modified[address] = true; + + uint8_t &tag = tags[address]; + if ( tag & MEMTAG_IGNORE ) return; + + if ( !(tag & MEMTAG_INST) ) { + tag |= ( MEMTAG_DATA | MEMTAG_TDATA ); + } + } + + void init() + { + for (int i=0; i<65536; ++i) { + breakpoints[i]=0; + tags[i] = MEMTAG_NONE; + } + if (!cur_df) cur_df = SDL_GetCursor(); + if (!cur_ns) cur_ns = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NS_RESIZE); + if (!cur_we) cur_we = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_EW_RESIZE); + + memchr(console_log, 0, 65536); + memchr(console_history, 0, 65536); + //show(); + } + + void show() + { + if (!win) { + win = SDL_CreateWindow("Z80 Debugger", 98*CHR_W, 44*CHR_H, 0/*SDL_WINDOW_RESIZABLE*/); + ren = SDL_CreateRenderer(win, 0); + ui::window::registerWindow(SDL_GetWindowID(win), eventHandler); + tex = ui::createtexture(ren); + } + SDL_StartTextInput(win); + focus(); + } + + void focus() + { + if (win) { + SDL_RaiseWindow(win); + refresh(); + } + } + + void hide() + { + SDL_StopTextInput(win); + ui::window::unregisterWindow(SDL_GetWindowID(win)); + if (tex) SDL_DestroyTexture(tex); + if (ren) SDL_DestroyRenderer(ren); + if (win) SDL_DestroyWindow(win); + tex = NULL; + ren = NULL; + win = NULL; + } + + void pause() + { + //speaker::disable(); + //is_paused = true; + breakpoints[z80::getPC()] &= ~8; + } + + void stop() + { + //history::gototop(); + //zxscreen::setTitle(" (stopped)"); + pause(); + //z80::resetStackedCalls(); + //is_debugging = true; + show(); + /*refresh();*/ + //if ( zxscreen::getFullRefresh()) zxscreen::fullrefresh(); + } + + void cont() { + display::setTitle(""); + //is_debugging = is_paused = false; + hide(); + refresh(); + display::focus(); + //speaker::enable(); + } + + uint16_t find_previous_opcode(uint16_t pc) + { + pc--; + if ( !(tags[pc] & (MEMTAG_CODE | MEMTAG_INST) ) ) return pc; + + while ( !(tags[pc] & MEMTAG_INST) ) pc--; + + return pc; + } + + void printDissasemblerLine(const uint16_t address, const int line, const bool heuristics=false) + { + uint8_t colors[4] = { COLOR_RED, COLOR_CYAN, COLOR_WHITE, COLOR_WHITE}; + const uint8_t tag = tags[address]; + if ( !(tag & (MEMTAG_TINST | MEMTAG_TREPEAT)) ) colors[3]=COLOR_GRAY; + if ( !(tag & MEMTAG_TOUCHED) ) colors[1]=COLOR_GRAY; + + if (msx::is_paused() && (address == z80::getPC())) { + for (int i=0; i<4;++i) colors[i]=COLOR_YELLOW; + ui::printrect(0,line, midx-2,1, COLOR_BLUE); + } + + if (breakpoints[address]&9) ui::printtxt(0,line,"*", colors[0]); + ui::printtxt(1,line,tohex(address,4), colors[1]); + + if ( (tag & MEMTAG_INST) || heuristics ) { + const char *sym = z80dis::getSymbol(address); + if (sym[0]!=0) ui::printtxt(7,line, sym, COLOR_YELLOW); + + const int opcodesize = z80dis::getOpcodeSize(address); + for (int i=0; i=0;--i) { + pos = find_previous_opcode(pos); + line_address[i] = pos; + printDissasemblerLine(pos, i); + } + + // REGISTERS + // ****************************************** + + ui::setoffset(0, 0); + ui::box(midx,0,25,8,COLOR_WHITE); + ui::printrect(midx+2,0, 12,1, COLOR_DARK); + ui::printtxt(midx+3,0, "REGISTERS:", COLOR_WHITE); + + ui::setoffset(midx+1, 1); + ui::printtxt(0,0, "AF AF' IX ", COLOR_WHITE); + ui::printtxt(0,1, "BC BC' IY ", COLOR_WHITE); + ui::printtxt(0,2, "DE DE' SP ", COLOR_WHITE); + ui::printtxt(0,3, "HL HL' PC ", COLOR_WHITE); + ui::printtxt(0,4, "(BC) (DE) (HL) ", COLOR_WHITE); + ui::printtxt(0,5, " I R ", COLOR_WHITE); + + ui::printtxt(3,0, tohex(z80::getAF(), 4), oAF != z80::getAF() ? COLOR_RED : COLOR_GRAY); + ui::printtxt(11,0, tohex(z80::getAF(true), 4), oAF2 != z80::getAF(true) ? COLOR_RED : COLOR_GRAY); + ui::printtxt(19,0, tohex(z80::getIX(), 4), oIX != z80::getIX() ? COLOR_RED : COLOR_GRAY); + ui::printtxt(3,1, tohex(z80::getBC(), 4), oBC != z80::getBC() ? COLOR_RED : COLOR_GRAY); + ui::printtxt(11,1, tohex(z80::getBC(true), 4), oBC2 != z80::getBC(true) ? COLOR_RED : COLOR_GRAY); + ui::printtxt(19,1, tohex(z80::getIY(), 4), oIY != z80::getIY() ? COLOR_RED : COLOR_GRAY); + ui::printtxt(3,2, tohex(z80::getDE(), 4), oDE != z80::getDE() ? COLOR_RED : COLOR_GRAY); + ui::printtxt(11,2, tohex(z80::getDE(true), 4), oDE2 != z80::getDE(true) ? COLOR_RED : COLOR_GRAY); + ui::printtxt(19,2, tohex(z80::getSP(), 4), oSP != z80::getSP() ? COLOR_RED : COLOR_GRAY); + ui::printtxt(3,3, tohex(z80::getHL(), 4), oHL != z80::getHL() ? COLOR_RED : COLOR_GRAY); + ui::printtxt(11,3, tohex(z80::getHL(true), 4), oHL2 != z80::getHL(true) ? COLOR_RED : COLOR_GRAY); + ui::printtxt(19,3, tohex(z80::getPC(), 4), oPC != z80::getPC() ? COLOR_RED : COLOR_GRAY); + + ui::printtxt(16,5, tohex(z80::getI(), 2), oI != z80::getI() ? COLOR_RED : COLOR_GRAY); + ui::printtxt(21,5, tohex(z80::getR(), 2), oR != z80::getR() ? COLOR_RED : COLOR_GRAY); + + ui::printtxt(5,4, tohex(mem::read(z80::getBC()), 2), COLOR_GRAY); + ui::printtxt(13,4, tohex(mem::read(z80::getDE()), 2), COLOR_GRAY); + ui::printtxt(21,4, tohex(mem::read(z80::getHL()), 2), COLOR_GRAY); + + const uint8_t flags = (z80::getAF() & 0xFF); + const uint8_t mod_flags = flags ^ (oAF & 0xFF); + ui::printtxt(0,5,"S", flags&0x80 ? (mod_flags&0x80 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x80 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(1,5,"Z", flags&0x40 ? (mod_flags&0x40 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x40 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(2,5,"X", flags&0x20 ? (mod_flags&0x20 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x20 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(3,5,"H", flags&0x10 ? (mod_flags&0x10 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x10 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(4,5,"Y", flags&0x08 ? (mod_flags&0x08 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x08 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(5,5,"P", flags&0x04 ? (mod_flags&0x04 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x04 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(6,5,"N", flags&0x02 ? (mod_flags&0x02 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x02 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(7,5,"C", flags&0x01 ? (mod_flags&0x01 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x01 ? COLOR_BROWN : COLOR_GRAY) ); + + + // STACK + // ****************************************** + ui::setoffset(0, 0); + ui::box(midx,8,11,12,COLOR_WHITE); + ui::printrect(midx+2,8, 8,1, COLOR_DARK); + ui::printtxt(midx+3,8, "STACK:", COLOR_WHITE); + ui::setoffset(midx+1, 9); + uint16_t sp = z80::getSP();//-(((sym_y-12)>>1)<<1); + for (int i=0; i<10; ++i) { + uint8_t c1=COLOR_CYAN, c2=COLOR_GRAY; + if (sp == z80::getSP()) { + ui::printrect(0,i,9,1,COLOR_BLUE); + c1 = c2 = COLOR_YELLOW; + } + ui::printtxt(0,i, tohex(sp, 4), c1); + uint16_t value = mem::read(sp) + (mem::read(sp+1)<<8); + ui::printtxt(5,i, tohex(value, 4), c2); + sp+=2; + } + + + // BREAKPOINTS + // ****************************************** + + ui::setoffset(0, 0); + ui::box(midx+11,8,14,12,COLOR_WHITE); + ui::printrect(midx+13,8, 9,1, COLOR_DARK); + ui::printtxt(midx+14,8, "BREAKS:", COLOR_WHITE); + ui::setoffset(midx+12, 9); + + int line=0; + num_breakpoint_lines=0; + for (int i=0; i<65536; ++i) { + if (breakpoints[i]&7) { + line_breakpoint_address[line] = i; + num_breakpoint_lines++; + uint8_t colors[2] = {COLOR_WHITE, COLOR_GRAY}; + if (i==cursor) { + ui::printrect(1,line,10,1,COLOR_BLUE); + colors[0]=colors[1]=COLOR_YELLOW; + } + ui::printtxt(2,line, tohex(i,4), colors[0]); + ui::printtxt(7,line, breakpoints[i]&1?"x":"-", colors[1]); + ui::printtxt(8,line, breakpoints[i]&2?"r":"-", colors[1]); + ui::printtxt(9,line, breakpoints[i]&4?"w":"-", colors[1]); + line++; + if (line>9) break; + } + } + + + // INSPECTOR + // ****************************************** + + ui::setoffset(0, 0); + ui::box(midx,20,25,4,COLOR_WHITE); + ui::printrect(midx+2,20,12,1, COLOR_DARK); + ui::printtxt(midx+3,20, "INSPECTOR:", COLOR_WHITE); + ui::setoffset(midx+1, 21); + + ui::printtxt(1,0,"VALUE:", COLOR_GRAY); ui::printtxt(8,0,"$", COLOR_CYAN); + ui::printtxt(9,0,tohex(inspected_value,4), COLOR_CYAN); + ui::printtxt(14,0,todec(inspected_value,false), COLOR_WHITE); + ui::printtxt(20,0,todec(inspected_value,true), COLOR_WHITE); + ui::printtxt(1,1,"H:", COLOR_GRAY); ui::printtxt(4,1,"$", COLOR_CYAN); + ui::printtxt(5,1,tohex(inspected_value>>8,2), COLOR_CYAN); + ui::printtxt(8,1,todec(inspected_value>>8,false), COLOR_WHITE); + ui::printtxt(12,1,"L:", COLOR_GRAY); ui::printtxt(15,1,"$", COLOR_CYAN); + ui::printtxt(16,1,tohex(inspected_value&0xff,2), COLOR_CYAN); + ui::printtxt(19,1,todec(inspected_value&0xff,false), COLOR_WHITE); + + // MEMORY + // ****************************************** + + ui::setoffset(0, 0); + ui::box(0,mem_y,midx,mem_h,COLOR_WHITE); + ui::printrect(2,mem_y, 11,1, COLOR_DARK); + ui::printtxt(3,mem_y, "MEMORY:", COLOR_WHITE); + + ui::printvoidrect(10,mem_y,3,1,COLOR_WHITE); + if (sync_mem_with_cursor) ui::printchar(11,mem_y,'X',COLOR_WHITE); + + ui::setoffset(1, mem_y+1); + + uint16_t mem_viewer_cursor = mem_viewer_pos; + for (int i=0; i", COLOR_WHITE); + ui::printtxt(1,line, console_history[console_history_nav], COLOR_WHITE); + ui::printtxt(strlen(console_history[console_history_nav])+1,line, "\x7F", COLOR_WHITE); + uint8_t i = console_log_pos; + while (line>0) { + line--; + ui::printtxt(1,line, console_log[i--], COLOR_GRAY); + } + + + // SYMBOLS + // ***************************************** + + ui::setoffset(0, 0); + ui::box(midx,sym_y,25,sym_h,COLOR_WHITE); + ui::printrect(midx+2,sym_y, 9,1, COLOR_DARK); + ui::printtxt(midx+3,sym_y, "SYMBOLS:", COLOR_WHITE); + + ui::setoffset(midx+1, sym_y+1); + const int num_symbols = z80dis::getNumSymbols(); + for (int i=0;i"); + strcat(console_log[console_log_pos], console_history[console_history_pos]); + processCommand(); + console_history_pos++; + console_history_nav=console_history_pos; + console_history[console_history_pos][0] = 0; + refresh(); + } + + const char integer_digits[] = "0123456789"; + const char hex_digits[] = "0123456789ABCDEF"; + + const int getnum(const char *str) + { + int i=0; + int return_value = 0; + if (str[0]=='$') { + i++; + while(str[i]!=0) { + int num = str[i]-48; + if (num<0) return -1; + if (num>9) { + num-=7; + if (num>15) { + num-=32; + if (num<10 || num>15) return -1; + } + } + return_value = (return_value<<4)+num; + i++; + } + } else { + while(str[i]!=0) { + int num = str[i]-48; + if (num<0 || num>9) return -1; + return_value = (return_value*10)+num; + i++; + } + } + return return_value; + } + +#define getcmd() {while (*console_ptr==32) console_ptr++;while (console_ptr[i]!=0 && console_ptr[i]!=32) { cmd[i]=console_ptr[i]; i++; } cmd[i]=0; console_ptr = &console_ptr[i]; i=0;} + + void processCommand() + { + char cmd[256]; + int i=0; + char *console_ptr = console_history[console_history_pos]; + + getcmd(); + + if (strcmp(cmd, "s")==0 || strcmp(cmd, "step")==0){ + msx::step(); + display::redraw(); + } else if (strcmp(cmd, "c")==0 || strcmp(cmd, "cont")==0) { + msx::resume(); + } else if (strcmp(cmd, "r")==0 || strcmp(cmd, "reset")==0) { + msx::init(); + history::reset(); + } else if (strcmp(cmd, "b")==0 || strcmp(cmd, "break")==0) { + getcmd(); + if (cmd[0] == 0) { breakpoints[z80::getPC()]=1; return; } + if (cmd[0] == 'i') { z80::setOption(Z80_OPTION_BREAK_ON_INTERRUPT, !z80::getOption(Z80_OPTION_BREAK_ON_INTERRUPT)); sendToConsoleLog("Break on interrupt."); return; } + int address = getnum(cmd); + if (address<0 || address>65536) { sendToConsoleLog("Illegal break address"); return; } + getcmd(); + uint8_t break_type = 1; + if (cmd[0]!=0) { + if (strcmp(cmd, "x")==0 || strcmp(cmd, "exec")==0) { + break_type = 1; + } else if (strcmp(cmd, "r")==0 || strcmp(cmd, "read")==0) { + break_type = 2; + } else if (strcmp(cmd, "w")==0 || strcmp(cmd, "write")==0) { + break_type = 4; + } else { + sendToConsoleLog("Illegal break type"); + return; + } + } + breakpoints[address] |= break_type; + } else if (strcmp(cmd, "d")==0 || strcmp(cmd, "delete")==0) { + getcmd(); + if (strcmp(cmd, "all")==0) { for (int i=0;i<65536;++i) breakpoints[i]=0; return; } + if (cmd[0] == 0) { breakpoints[z80::getPC()]=0; return; } + int address = getnum(cmd); + if (address<0 || address>65536) { sendToConsoleLog("Illegal address"); return; } + getcmd(); + uint8_t break_type = 7; + if (cmd[0]!=0) { + if (strcmp(cmd, "x")==0 || strcmp(cmd, "exec")==0) { + break_type = 1; + } else if (strcmp(cmd, "r")==0 || strcmp(cmd, "read")==0) { + break_type = 2; + } else if (strcmp(cmd, "w")==0 || strcmp(cmd, "write")==0) { + break_type = 4; + } else { + sendToConsoleLog("Illegal break type"); + return; + } + } + breakpoints[address] &= ~break_type; + } else if (strcmp(cmd, "m")==0 || strcmp(cmd, "mem")==0) { + getcmd(); + int address = getnum(cmd); + if (address<0 || address>65536) { sendToConsoleLog("Illegal memory address"); return; } + mem_viewer_pos = address; + } else if (strcmp(cmd, "st")==0 || strcmp(cmd, "save")==0) { + getcmd(); + char filename[256]; + strcpy(filename, cmd); + savestate(filename); + } else if (strcmp(cmd, "l")==0 || strcmp(cmd, "load")==0) { + getcmd(); + char filename[256]; + strcpy(filename, cmd); + loadstate(filename); + } else if (strcmp(cmd, "t")==0 || strcmp(cmd, "tape")==0) { + getcmd(); + if (strcmp(cmd, "load")==0) { + getcmd(); + char filename[256]; + strcpy(filename, cmd); + cassette::load_cas_file(filename); + } else if (strcmp(cmd, "play")==0) { + //zx_tape::play(); + } + } else if (strcmp(cmd, "disk")==0) { + getcmd(); + if (strcmp(cmd, "load")==0) { + getcmd(); + char filename[256]; + strcpy(filename, cmd); + //zx_disk::load(filename); + } + } else if (strcmp(cmd, "poke")==0) { + getcmd(); + int address = getnum(cmd); + getcmd(); + int value = getnum(cmd); + mem::write(address, value); + } else if (strcmp(cmd, "peek")==0) { + getcmd(); + int address = getnum(cmd); + int value = mem::read(address); + char tmp[10]; + sendToConsoleLog(SDL_itoa(value, tmp, 10)); + } else if (strcmp(cmd, "reg")==0) { + getcmd(); + if (strcmp(cmd, "f")==0) { getcmd(); int value = getnum(cmd); z80::getRegs()[0] = value; } + else if (strcmp(cmd, "a")==0) { getcmd(); int value = getnum(cmd); z80::getRegs()[1] = value; } + else if (strcmp(cmd, "c")==0) { getcmd(); int value = getnum(cmd); z80::getRegs()[2] = value; } + else if (strcmp(cmd, "b")==0) { getcmd(); int value = getnum(cmd); z80::getRegs()[3] = value; } + else if (strcmp(cmd, "e")==0) { getcmd(); int value = getnum(cmd); z80::getRegs()[4] = value; } + else if (strcmp(cmd, "d")==0) { getcmd(); int value = getnum(cmd); z80::getRegs()[5] = value; } + else if (strcmp(cmd, "l")==0) { getcmd(); int value = getnum(cmd); z80::getRegs()[6] = value; } + else if (strcmp(cmd, "h")==0) { getcmd(); int value = getnum(cmd); z80::getRegs()[7] = value; } + else if (strcmp(cmd, "pc")==0) { getcmd(); int value = getnum(cmd); z80::getRegs()[24] = value&0xff; z80::getRegs()[25] = (value>>8)&0xff; } + else { sendToConsoleLog("Syntax error: invalid register"); return; } + } else if (strcmp(cmd, "g")==0 || strcmp(cmd, "goto")==0) { + getcmd(); + int address = getnum(cmd); + if (address<0 || address>=65536) { sendToConsoleLog("Illegal address"); return; } + if ( !(tags[address] & MEMTAG_INST) ) address = find_previous_opcode(address); + setcursor(address); + } else if (strcmp(cmd, "sym")==0 || strcmp(cmd, "symbol")==0) { + getcmd(); + if (strcmp(cmd, "add")==0) { + getcmd(); + char tmp[12]; strcpy(tmp, cmd); + getcmd(); + if (cmd[0]==0) { + z80dis::setSymbol(z80::getPC(), tmp); + } else { + int value = getnum(cmd); + z80dis::setSymbol(value, tmp); + } + sendToConsoleLog("Symbol added"); + } else if (strcmp(cmd, "del")==0) { + getcmd(); + if (cmd[0]==0) { + z80dis::setSymbol(z80::getPC(), NULL); + } else { + int value = getnum(cmd); + z80dis::setSymbol(value, NULL); + } + sendToConsoleLog("Symbol removed"); + } + } else if (strcmp(cmd, "ula")==0) { + getcmd(); + if (strcmp(cmd, "keydown")==0) { + getcmd(); + //zx_ula::keydown(cmd[0]); + sendToConsoleLog("Keydown sent for key: "); + sendMoreToConsoleLog(cmd); + } else if (strcmp(cmd, "keyup")==0) { + getcmd(); + //zx_ula::keyup(cmd[0]); + sendToConsoleLog("Keyup sent for key: "); + sendMoreToConsoleLog(cmd); + } + } else if (strcmp(cmd, "opcodes")==0) { + getcmd(); + if (strcmp(cmd, "clear")==0 || strcmp(cmd, "reset")==0) { + clearUsedOpcodes(); + } else if (strcmp(cmd, "mark")==0) { + markUsedOpcodes(); + } else if (strcmp(cmd, "count")==0) { + printf("Num opcodes used: %i\n", getNumOpcodesUsed()); + } else if (strcmp(cmd, "print")==0) { + printOpcodesUsed(); + } + } else if (strcmp(cmd, "ignore")==0) { + getcmd(); + const int address = getnum(cmd); + tags[address] |= MEMTAG_IGNORE; + } else if (strcmp(cmd, "search")==0) { + getcmd(); + if (strcmp(cmd, "next")==0) { + search(); + } else { + search(cmd); + } + } else if (strcmp(cmd, "show")==0) { + getcmd(); + if (strcmp(cmd, "analyzer")==0) { + //z80analyze::show(); + } else { + sendToConsoleLog("Unrecognized window. Usage: Show [analyzer]"); + } + } else { + sendToConsoleLog("Unrecognized command."); + } + } + + const bool isbreak(const uint16_t address, const uint8_t type) + { + return (breakpoints[address]&type); + } + + uint32_t next() + { + breakpoints[z80::getPC()+z80dis::getOpcodeSize(z80::getPC())] |= 8; + const uint32_t t = z80::step(); + cont(); + return t; + } + + uint32_t stepout() + { + z80::setOption(Z80_OPTION_BREAK_ON_RET, true); + const uint32_t t = z80::step(); + cont(); + return t; + } + + void setmemmodified(const uint16_t addr) + { + mem_modified[addr] = true; + } + + void loadngo(const char* filename, const char* addr) + { + /* + int address = getnum(addr); + if (address<0 || address>65536) { sendToConsoleLog("Illegal offset"); return; } + + FILE *f = fopen(filename, "rb"); + fseek(f, 0, SEEK_END); + int size = ftell(f); + fseek(f, 0, SEEK_SET); + uint32_t memsize; + uint8_t *memory = mem::getRawPointer(&memsize); + fread(memory+address, size, 1, f); + fclose(f); + z80::setPC(address); + is_debugging = is_paused = false; + */ + } + + void savestate(const char *filename) + { + //uint8_t *regs = z80::getRegs(); + //FILE *f = fopen(filename, "wb"); + //fwrite(regs, 31, 1, f); + //mem::saveState(f); + //fclose(f); + } + + void loadstate(const char *filename) + { + //uint8_t *regs = z80::getRegs(); + //FILE *f = fopen(filename, "rb"); + //fread(regs, 31, 1, f); + //mem::loadState(f); + //fclose(f); + //history::store(); + //history::gototop(); + } + + void setcursor(const uint16_t address) + { + //if (!debugging()) return; + if ( !(tags[address] & MEMTAG_INST) ) + cursor = find_previous_opcode(address); + else + cursor = address; + } + + void cursorfwd() + { + cursor += z80dis::getOpcodeSize(cursor); + } + + void cursorback() + { + cursor = find_previous_opcode(cursor); + } + + void useOpcode(const uint8_t opcode, const uint8_t base) + { + if (use[base][opcode]<255) use[base][opcode]++; + } + + void clearUsedOpcodes() + { + for (int i=0; i<7; ++i) { + for (int j=0; j<256; ++j) { + use[i][j]=0; + } + } + } + + void markUsedOpcodes() + { + for (int i=0; i<7; ++i) { + for (int j=0; j<256; ++j) { + if (use[i][j]==1) use[i][j]++; + } + } + } + + const int getNumOpcodesUsed() + { + int count = 0; + for (int i=0; i<7; ++i) { + for (int j=0; j<256; ++j) { + if (use[i][j]==1) count++; + } + } + return count; + } + + void printOpcodesUsed() + { + for (int i=0; i<7; ++i) { + for (int j=0; j<256; ++j) { + if (use[i][j]==1) { + switch (i) { + case 1: printf("ED "); break; + case 2: printf("CB "); break; + case 3: printf("DD "); break; + case 4: printf("DD CB "); break; + case 5: printf("FD "); break; + case 6: printf("FD CB "); break; + } + printf("%2X\n",j); + } + } + } + } + + uint8_t hexchartonum(char chr) + { + int num = chr-48; + if (num<0) return 0; + if (num>9) { + num-=7; + if (num>15) { + num-=32; + if (num<10 || num>15) return 0; + } + } + return uint8_t(num); + } + void search(const char *seq) + { + if (seq) { + search_pos = 0; + search_sequence_len=0; + while (*seq!=0) search_sequence[search_sequence_len++] = (hexchartonum(*(seq++))<<4) + hexchartonum(*(seq++)); + } + int num_found=0; + while (search_pos<65536) { + if (search_sequence[num_found] == mem::read(search_pos)) { + num_found++; search_pos++; + if (num_found==search_sequence_len) { + mem_viewer_pos=search_pos-search_sequence_len; + return; + } + } else { + num_found=0; search_pos++; + } + } + sendToConsoleLog("Sequence not found."); + } + + + namespace history + { + void reset() + { + buffer[0]=buffer[1]=0; + cursor=pos=top=0; + } + + void store() + { + buffer[++top] = z80::getPC(); + pos=top; + } + + void gototop() + { + pos = top; + z80::setPC(buffer[pos]); + cursor = z80::getPC(); + } + + void goforward() + { + if (pos == top) return; + z80::setPC(buffer[++pos]); + cursor = z80::getPC(); + } + + void goback() + { + if (uint8_t(pos-1) == top) return; + z80::setPC(buffer[--pos]); + cursor = z80::getPC(); + } + + } + +} diff --git a/z80debugger.h b/z80debugger.h new file mode 100644 index 0000000..36fe009 --- /dev/null +++ b/z80debugger.h @@ -0,0 +1,71 @@ +#pragma once +#include + +namespace z80debugger +{ + #define MEMTAG_NONE 0x00 + #define MEMTAG_DATA 0x01 + #define MEMTAG_INST 0x02 + #define MEMTAG_CODE 0x04 + #define MEMTAG_IGNORE 0x08 + #define MEMTAG_TDATA 0x10 + #define MEMTAG_TINST 0x20 + #define MEMTAG_TREPEAT 0x40 + #define MEMTAG_MODIFIED 0x80 + + #define MEMTAG_KNOWN 0x07 + #define MEMTAG_TOUCHED 0x70 + + uint8_t getTag(uint16_t address); + void setTag(uint16_t address, uint8_t value); + + void onInstructionExecute(uint16_t address); + void onMemRead(uint16_t address, bool code=false); + void onMemWrite(uint16_t address); + + void init(); + void show(); + void focus(); + void hide(); + + void pause(); + void stop(); + void cont(); + void setmemmodified(const uint16_t addr); + + void refresh(); + void sendToConsole(const char* text); + void sendToConsoleLog(const char *text); + void sendMoreToConsoleLog(const char *text); + void DeleteCharConsole(); + void executeConsole(); + + const bool isbreak(const uint16_t address, const uint8_t type=1); + uint32_t next(); + uint32_t stepout(); + + void savestate(const char *filename); + void loadstate(const char *filename); + + void loadngo(const char* filename, const char* addr); + + void setcursor(const uint16_t address); + void cursorfwd(); + void cursorback(); + + void useOpcode(const uint8_t opcode, const uint8_t base); + void clearUsedOpcodes(); + void markUsedOpcodes(); + const int getNumOpcodesUsed(); + void printOpcodesUsed(); + + void search(const char *seq=nullptr); + namespace history + { + void reset(); + void store(); + void gototop(); + void goforward(); + void goback(); + } +} diff --git a/z80dis.cpp b/z80dis.cpp new file mode 100644 index 0000000..27cb333 --- /dev/null +++ b/z80dis.cpp @@ -0,0 +1,241 @@ +#include "z80dis.h" +#include "z80.h" +#include "mem.h" +#include +#include +#include +#include + +namespace z80dis +{ + char buffer[256]; + int opcode_size = 0; + char symbols[65536][15]; + std::vector used_symbols; + +// $%04x +// $%02x +// %hhd + + const char *base_opcodes[256] = {"nop", "ld bc,$%04x", "ld (bc),a", "inc bc", "inc b", "dec b", "ld b,$%02x", "rlca", "ex af,af'", "add hl,bc", "ld a,(bc)", "dec bc", "inc c", "dec c", "ld c,$%02x", "rrca", "djnz $%Xx", "ld de,$%04x", "ld (de),a", "inc de", "inc d", "dec d", "ld d,$%02x", "rla", "jr $%Xx", "add hl,de", "ld a,(de)", "dec de", "inc e", "dec e", "ld e,$%02x", "rra", "jr nz,$%Xx", "ld hl,$%04x", "ld ($%04x),hl", "inc hl", "inc h", "dec h", "ld h,$%02x", "daa", "jr z,$%Xx", "add hl,hl", "ld hl,($%04x)", "dec hl", "inc l", "dec l", "ld l,$%02x", "cpl", "jr nc,$%Xx", "ld sp,$%04x", "ld ($%04x),a", "inc sp", "inc (hl)", "dec (hl)", "ld (hl),$%02x", "scf", "jr c,$%Xx", "add hl,sp", "ld a,($%04x)", "dec sp", "inc a", "dec a", "ld a,$%02x", "ccf", "ld b,b", "ld b,c", "ld b,d", "ld b,e", "ld b,h", "ld b,l", "ld b,(hl)", "ld b,a", "ld c,b", "ld c,c", "ld c,d", "ld c,e", "ld c,h", "ld c,l", "ld c,(hl)", "ld c,a", "ld d,b", "ld d,c", "ld d,d", "ld d,e", "ld d,h", "ld d,l", "ld d,(hl)", "ld d,a", "ld e,b", "ld e,c", "ld e,d", "ld e,e", "ld e,h", "ld e,l", "ld e,(hl)", "ld e,a", "ld h,b", "ld h,c", "ld h,d", "ld h,e", "ld h,h", "ld h,l", "ld h,(hl)", "ld h,a", "ld l,b", "ld l,c", "ld l,d", "ld l,e", "ld l,h", "ld l,l", "ld l,(hl)", "ld l,a", "ld (hl),b", "ld (hl),c", "ld (hl),d", "ld (hl),e", "ld (hl),h", "ld (hl),l", "halt", "ld (hl),a", "ld a,b", "ld a,c", "ld a,d", "ld a,e", "ld a,h", "ld a,l", "ld a,(hl)", "ld a,a", "add a,b", "add a,c", "add a,d", "add a,e", "add a,h", "add a,l", "add a,(hl)", "add a,a", "adc a,b", "adc a,c", "adc a,d", "adc a,e", "adc a,h", "adc a,l", "adc a,(hl)", "adc a,a", "sub b", "sub c", "sub d", "sub e", "sub h", "sub l", "sub (hl)", "sub a", "sbc a,b", "sbc a,c", "sbc a,d", "sbc a,e", "sbc a,h", "sbc a,l", "sbc a,(hl)", "sbc a,a", "and b", "and c", "and d", "and e", "and h", "and l", "and (hl)", "and a", "xor b", "xor c", "xor d", "xor e", "xor h", "xor l", "xor (hl)", "xor a", "or b", "or c", "or d", "or e", "or h", "or l", "or (hl)", "or a", "cp b", "cp c", "cp d", "cp e", "cp h", "cp l", "cp (hl)", "cp a", "ret nz", "pop bc", "jp nz,$%04x", "jp $%04x", "call nz,$%04x", "push bc", "add a,$%02x", "rst 00h", "ret z", "ret", "jp z,$%04x", "_Bit_", "call z,$%04x", "call $%04x", "adc a,$%02x", "rst 08h", "ret nc", "pop de", "jp nc,$%04x", "out ($%02x),a", "call nc,$%04x", "push de", "sub $%02x", "rst 10h", "ret c", "exx", "jp c,$%04x", "in a,($%02x)", "call c,$%04x", "_IX_", "sbc a,$%02x", "rst 18h", "ret po", "pop hl", "jp po,$%04x", "ex (sp),hl", "call po,$%04x", "push hl", "and $%02x", "rst 20h", "ret pe", "jp (hl)", "jp pe,$%04x", "ex de,hl", "call pe,$%04x", "_Misc._", "xor $%02x", "rst 28h", "ret p", "pop af", "jp p,$%04x", "di", "call p,$%04x", "push af", "or $%02x", "rst 30h", "ret m", "ld sp,hl", "jp m,$%04x", "ei", "call m,$%04x", "_IY_", "cp $%02x", "rst 38h"}; + const char *cb_opcodes[256] = {"rlc b", "rlc c", "rlc d", "rlc e", "rlc h", "rlc l", "rlc (hl)", "rlc a", "rrc b", "rrc c", "rrc d", "rrc e", "rrc h", "rrc l", "rrc (hl)", "rrc a", "rl b", "rl c", "rl d", "rl e", "rl h", "rl l", "rl (hl)", "rl a", "rr b", "rr c", "rr d", "rr e", "rr h", "rr l", "rr (hl)", "rr a", "sla b", "sla c", "sla d", "sla e", "sla h", "sla l", "sla (hl)", "sla a", "sra b", "sra c", "sra d", "sra e", "sra h", "sra l", "sra (hl)", "sra a", "sll b", "sll c", "sll d", "sll e", "sll h", "sll l", "sll (hl)", "sll a", "srl b", "srl c", "srl d", "srl e", "srl h", "srl l", "srl (hl)", "srl a", "bit 0,b", "bit 0,c", "bit 0,d", "bit 0,e", "bit 0,h", "bit 0,l", "bit 0,(hl)", "bit 0,a", "bit 1,b", "bit 1,c", "bit 1,d", "bit 1,e", "bit 1,h", "bit 1,l", "bit 1,(hl)", "bit 1,a", "bit 2,b", "bit 2,c", "bit 2,d", "bit 2,e", "bit 2,h", "bit 2,l", "bit 2,(hl)", "bit 2,a", "bit 3,b", "bit 3,c", "bit 3,d", "bit 3,e", "bit 3,h", "bit 3,l", "bit 3,(hl)", "bit 3,a", "bit 4,b", "bit 4,c", "bit 4,d", "bit 4,e", "bit 4,h", "bit 4,l", "bit 4,(hl)", "bit 4,a", "bit 5,b", "bit 5,c", "bit 5,d", "bit 5,e", "bit 5,h", "bit 5,l", "bit 5,(hl)", "bit 5,a", "bit 6,b", "bit 6,c", "bit 6,d", "bit 6,e", "bit 6,h", "bit 6,l", "bit 6,(hl)", "bit 6,a", "bit 7,b", "bit 7,c", "bit 7,d", "bit 7,e", "bit 7,h", "bit 7,l", "bit 7,(hl)", "bit 7,a", "res 0,b", "res 0,c", "res 0,d", "res 0,e", "res 0,h", "res 0,l", "res 0,(hl)", "res 0,a", "res 1,b", "res 1,c", "res 1,d", "res 1,e", "res 1,h", "res 1,l", "res 1,(hl)", "res 1,a", "res 2,b", "res 2,c", "res 2,d", "res 2,e", "res 2,h", "res 2,l", "res 2,(hl)", "res 2,a", "res 3,b", "res 3,c", "res 3,d", "res 3,e", "res 3,h", "res 3,l", "res 3,(hl)", "res 3,a", "res 4,b", "res 4,c", "res 4,d", "res 4,e", "res 4,h", "res 4,l", "res 4,(hl)", "res 4,a", "res 5,b", "res 5,c", "res 5,d", "res 5,e", "res 5,h", "res 5,l", "res 5,(hl)", "res 5,a", "res 6,b", "res 6,c", "res 6,d", "res 6,e", "res 6,h", "res 6,l", "res 6,(hl)", "res 6,a", "res 7,b", "res 7,c", "res 7,d", "res 7,e", "res 7,h", "res 7,l", "res 7,(hl)", "res 7,a", "set 0,b", "set 0,c", "set 0,d", "set 0,e", "set 0,h", "set 0,l", "set 0,(hl)", "set 0,a", "set 1,b", "set 1,c", "set 1,d", "set 1,e", "set 1,h", "set 1,l", "set 1,(hl)", "set 1,a", "set 2,b", "set 2,c", "set 2,d", "set 2,e", "set 2,h", "set 2,l", "set 2,(hl)", "set 2,a", "set 3,b", "set 3,c", "set 3,d", "set 3,e", "set 3,h", "set 3,l", "set 3,(hl)", "set 3,a", "set 4,b", "set 4,c", "set 4,d", "set 4,e", "set 4,h", "set 4,l", "set 4,(hl)", "set 4,a", "set 5,b", "set 5,c", "set 5,d", "set 5,e", "set 5,h", "set 5,l", "set 5,(hl)", "set 5,a", "set 6,b", "set 6,c", "set 6,d", "set 6,e", "set 6,h", "set 6,l", "set 6,(hl)", "set 6,a", "set 7,b", "set 7,c", "set 7,d", "set 7,e", "set 7,h", "set 7,l", "set 7,(hl)", "set 7,a"}; + const char *ix_opcodes[256] = {"", "", "", "", "inc b", "dec b", "ld b,$%02x", "", "", "add ix,bc", "", "", "inc c", "dec c", "ld c,$%02x", "", "", "", "", "", "inc d", "dec d", "ld d,$%02x", "", "", "add ix,de", "", "", "inc e", "dec e", "ld e,$%02x", "", "", "ld ix,$%04x", "ld ($%04x),ix", "inc ix", "inc ixh", "dec ixh", "ld ixh,$%02x", "", "", "add ix,ix", "ld ix,($%04x)", "dec ix", "inc ixl", "dec ixl", "ld ixl,$%02x", "", "", "", "", "", "inc (ix+%hhd)", "dec (ix+%hhd)", "ld (ix+%hhd),$%02x", "", "", "add ix,sp", "", "", "inc a", "dec a", "ld a,$%02x", "", "ld b,b", "ld b,c", "ld b,d", "ld b,e", "ld b,ixh", "ld b,ixl", "ld b,(ix+%hhd)", "ld b,a", "ld c,b", "ld c,c", "ld c,d", "ld c,e", "ld c,ixh", "ld c,ixl", "ld c,(ix+%hhd)", "ld c,a", "ld d,b", "ld d,c", "ld d,d", "ld d,e", "ld d,ixh", "ld d,ixl", "ld d,(ix+%hhd)", "ld d,a", "ld e,b", "ld e,c", "ld e,d", "ld e,e", "ld e,ixh", "ld e,ixl", "ld e,(ix+%hhd)", "ld e,a", "ld ixh,b", "ld ixh,c", "ld ixh,d", "ld ixh,e", "ld ixh,ixh", "ld ixh,ixl", "ld h,(ix+%hhd)", "ld ixh,a", "ld ixl,b", "ld ixl,c", "ld ixl,d", "ld ixl,e", "ld ixl,ixh", "ld ixl,ixl", "ld l,(ix+%hhd)", "ld ixl,a", "ld (ix+%hhd),b", "ld (ix+%hhd),c", "ld (ix+%hhd),d", "ld (ix+%hhd),e", "ld (ix+%hhd),h", "ld (ix+%hhd),l", "", "ld (ix+%hhd),a", "ld a,b", "ld a,c", "ld a,d", "ld a,e", "ld a,ixh", "ld a,ixl", "ld a,(ix+%hhd)", "ld a,a", "add a,b", "add a,c", "add a,d", "add a,e", "add a,ixh", "add a,ixl", "add a,(ix+%hhd)", "add a,a", "adc a,b", "adc a,c", "adc a,d", "adc a,e", "adc a,ixh", "adc a,ixl", "adc a,(ix+%hhd)", "adc a,a", "sub b", "sub c", "sub d", "sub e", "sub ixh", "sub ixl", "sub (ix+%hhd)", "sub a", "sbc a,b", "sbc a,c", "sbc a,d", "sbc a,e", "sbc a,ixh", "sbc a,ixl", "sbc a,(ix+%hhd)", "sbc a,a", "and b", "and c", "and d", "and e", "and ixh", "and ixl", "and (ix+%hhd)", "and a", "xor b", "xor c", "xor d", "xor e", "xor ixh", "xor ixl", "xor (ix+%hhd)", "xor a", "or b", "or c", "or d", "or e", "or ixh", "or ixl", "or (ix+%hhd)", "or a", "cp b", "cp c", "cp d", "cp e", "cp ixh", "cp ixl", "cp (ix+%hhd)", "cp a", "", "", "", "", "", "", "", "", "", "", "", "_IX Bit_", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "pop ix", "", "ex (sp),ix", "", "push ix", "", "", "", "jp (ix)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ld sp,ix", "", "", "", "", "", ""}; + const char *ix_bit_opcodes[256] = {"rlc (ix+%hhd),b", "rlc (ix+%hhd),c", "rlc (ix+%hhd),d", "rlc (ix+%hhd),e", "rlc (ix+%hhd),h", "rlc (ix+%hhd),l", "rlc (ix+%hhd)", "rlc (ix+%hhd),a", "rrc (ix+%hhd),b", "rrc (ix+%hhd),c", "rrc (ix+%hhd),d", "rrc (ix+%hhd),e", "rrc (ix+%hhd),h", "rrc (ix+%hhd),l", "rrc (ix+%hhd)", "rrc (ix+%hhd),a", "rl (ix+%hhd),b", "rl (ix+%hhd),c", "rl (ix+%hhd),d", "rl (ix+%hhd),e", "rl (ix+%hhd),h", "rl (ix+%hhd),l", "rl (ix+%hhd)", "rl (ix+%hhd),a", "rr (ix+%hhd),b", "rr (ix+%hhd),c", "rr (ix+%hhd),d", "rr (ix+%hhd),e", "rr (ix+%hhd),h", "rr (ix+%hhd),l", "rr (ix+%hhd)", "rr (ix+%hhd),a", "sla (ix+%hhd),b", "sla (ix+%hhd),c", "sla (ix+%hhd),d", "sla (ix+%hhd),e", "sla (ix+%hhd),h", "sla (ix+%hhd),l", "sla (ix+%hhd)", "sla (ix+%hhd),a", "sra (ix+%hhd),b", "sra (ix+%hhd),c", "sra (ix+%hhd),d", "sra (ix+%hhd),e", "sra (ix+%hhd),h", "sra (ix+%hhd),l", "sra (ix+%hhd)", "sra (ix+%hhd),a", "sll (ix+%hhd),b", "sll (ix+%hhd),c", "sll (ix+%hhd),d", "sll (ix+%hhd),e", "sll (ix+%hhd),h", "sll (ix+%hhd),l", "sll (ix+%hhd)", "sll (ix+%hhd),a", "srl (ix+%hhd),b", "srl (ix+%hhd),c", "srl (ix+%hhd),d", "srl (ix+%hhd),e", "srl (ix+%hhd),h", "srl (ix+%hhd),l", "srl (ix+%hhd)", "srl (ix+%hhd),a", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "res 0,(ix+%hhd),b", "res 0,(ix+%hhd),c", "res 0,(ix+%hhd),d", "res 0,(ix+%hhd),e", "res 0,(ix+%hhd),h", "res 0,(ix+%hhd),l", "res 0,(ix+%hhd)", "res 0,(ix+%hhd),a", "res 1,(ix+%hhd),b", "res 1,(ix+%hhd),c", "res 1,(ix+%hhd),d", "res 1,(ix+%hhd),e", "res 1,(ix+%hhd),h", "res 1,(ix+%hhd),l", "res 1,(ix+%hhd)", "res 1,(ix+%hhd),a", "res 2,(ix+%hhd),b", "res 2,(ix+%hhd),c", "res 2,(ix+%hhd),d", "res 2,(ix+%hhd),e", "res 2,(ix+%hhd),h", "res 2,(ix+%hhd),l", "res 2,(ix+%hhd)", "res 2,(ix+%hhd),a", "res 3,(ix+%hhd),b", "res 3,(ix+%hhd),c", "res 3,(ix+%hhd),d", "res 3,(ix+%hhd),e", "res 3,(ix+%hhd),h", "res 3,(ix+%hhd),l", "res 3,(ix+%hhd)", "res 3,(ix+%hhd),a", "res 4,(ix+%hhd),b", "res 4,(ix+%hhd),c", "res 4,(ix+%hhd),d", "res 4,(ix+%hhd),e", "res 4,(ix+%hhd),h", "res 4,(ix+%hhd),l", "res 4,(ix+%hhd)", "res 4,(ix+%hhd),a", "res 5,(ix+%hhd),b", "res 5,(ix+%hhd),c", "res 5,(ix+%hhd),d", "res 5,(ix+%hhd),e", "res 5,(ix+%hhd),h", "res 5,(ix+%hhd),l", "res 5,(ix+%hhd)", "res 5,(ix+%hhd),a", "res 6,(ix+%hhd),b", "res 6,(ix+%hhd),c", "res 6,(ix+%hhd),d", "res 6,(ix+%hhd),e", "res 6,(ix+%hhd),h", "res 6,(ix+%hhd),l", "res 6,(ix+%hhd)", "res 6,(ix+%hhd),a", "res 7,(ix+%hhd),b", "res 7,(ix+%hhd),c", "res 7,(ix+%hhd),d", "res 7,(ix+%hhd),e", "res 7,(ix+%hhd),h", "res 7,(ix+%hhd),l", "res 7,(ix+%hhd)", "res 7,(ix+%hhd),a", "set 0,(ix+%hhd),b", "set 0,(ix+%hhd),c", "set 0,(ix+%hhd),d", "set 0,(ix+%hhd),e", "set 0,(ix+%hhd),h", "set 0,(ix+%hhd),l", "set 0,(ix+%hhd)", "set 0,(ix+%hhd),a", "set 1,(ix+%hhd),b", "set 1,(ix+%hhd),c", "set 1,(ix+%hhd),d", "set 1,(ix+%hhd),e", "set 1,(ix+%hhd),h", "set 1,(ix+%hhd),l", "set 1,(ix+%hhd)", "set 1,(ix+%hhd),a", "set 2,(ix+%hhd),b", "set 2,(ix+%hhd),c", "set 2,(ix+%hhd),d", "set 2,(ix+%hhd),e", "set 2,(ix+%hhd),h", "set 2,(ix+%hhd),l", "set 2,(ix+%hhd)", "set 2,(ix+%hhd),a", "set 3,(ix+%hhd),b", "set 3,(ix+%hhd),c", "set 3,(ix+%hhd),d", "set 3,(ix+%hhd),e", "set 3,(ix+%hhd),h", "set 3,(ix+%hhd),l", "set 3,(ix+%hhd)", "set 3,(ix+%hhd),a", "set 4,(ix+%hhd),b", "set 4,(ix+%hhd),c", "set 4,(ix+%hhd),d", "set 4,(ix+%hhd),e", "set 4,(ix+%hhd),h", "set 4,(ix+%hhd),l", "set 4,(ix+%hhd)", "set 4,(ix+%hhd),a", "set 5,(ix+%hhd),b", "set 5,(ix+%hhd),c", "set 5,(ix+%hhd),d", "set 5,(ix+%hhd),e", "set 5,(ix+%hhd),h", "set 5,(ix+%hhd),l", "set 5,(ix+%hhd)", "set 5,(ix+%hhd),a", "set 6,(ix+%hhd),b", "set 6,(ix+%hhd),c", "set 6,(ix+%hhd),d", "set 6,(ix+%hhd),e", "set 6,(ix+%hhd),h", "set 6,(ix+%hhd),l", "set 6,(ix+%hhd)", "set 6,(ix+%hhd),a", "set 7,(ix+%hhd),b", "set 7,(ix+%hhd),c", "set 7,(ix+%hhd),d", "set 7,(ix+%hhd),e", "set 7,(ix+%hhd),h", "set 7,(ix+%hhd),l", "set 7,(ix+%hhd)", "set 7,(ix+%hhd),a"}; + const char *misc_opcodes[128] = {"in b,(c)", "out (c),b", "sbc hl,bc", "ld ($%04x),bc", "neg", "retn", "im 0", "ld i,a", "in c,(c)", "out (c),c", "adc hl,bc", "ld bc,($%04x)", "mlt bc", "reti", "", "ld r,a", "in d,(c)", "out (c),d", "sbc hl,de", "ld ($%04x),de", "", "", "im 1", "ld a,i", "in e,(c)", "out (c),e", "adc hl,de", "ld de,($%04x)", "mlt de", "", "im 2", "ld a,r", "in h,(c)", "out (c),h", "sbc hl,hl", "ld ($%04x),hl", "tst $%02x", "", "", "rrd", "in l,(c)", "out (c),l", "adc hl,hl", "ld hl,($%04x)", "mlt hl", "", "", "rld", "in (c)", "out (c),0", "sbc hl,sp", "ld ($%04x),sp", "tstio $%02x", "", "slp", "", "in a,(c)", "out (c),a", "adc hl,sp", "ld sp,($%04x)", "mlt sp", "", "", "", "", "", "", "otim", "", "", "", "", "", "", "", "otdm", "", "", "", "", "", "", "", "otimr", "", "", "", "", "", "", "", "otdmr", "", "", "", "", "ldi", "cpi", "ini", "outi", "", "", "", "", "ldd", "cpd", "ind", "outd", "", "", "", "", "ldir", "cpir", "inir", "otir", "", "", "", "", "lddr", "cpdr", "indr", "otdr", "", "", "", ""}; + const char *iy_opcodes[256] = {"", "", "", "", "inc b", "dec b", "ld b,$%02x", "", "", "add iy,bc", "", "", "inc c", "dec c", "ld c,$%02x", "", "", "", "", "", "inc d", "dec d", "ld d,$%02x", "", "", "add iy,de", "", "", "inc e", "dec e", "ld e,$%02x", "", "", "ld iy,$%04x", "ld ($%04x),iy", "inc iy", "inc iyh", "dec iyh", "ld iyh,$%02x", "", "", "add iy,iy", "ld iy,($%04x)", "dec iy", "inc iyl", "dec iyl", "ld iyl,$%02x", "", "", "", "", "", "inc (iy+%hhd)", "dec (iy+%hhd)", "ld (iy+%hhd),$%02x", "", "", "add iy,sp", "", "", "inc a", "dec a", "ld a,$%02x", "", "ld b,b", "ld b,c", "ld b,d", "ld b,e", "ld b,iyh", "ld b,iyl", "ld b,(iy+%hhd)", "ld b,a", "ld c,b", "ld c,c", "ld c,d", "ld c,e", "ld c,iyh", "ld c,iyl", "ld c,(iy+%hhd)", "ld c,a", "ld d,b", "ld d,c", "ld d,d", "ld d,e", "ld d,iyh", "ld d,iyl", "ld d,(iy+%hhd)", "ld d,a", "ld e,b", "ld e,c", "ld e,d", "ld e,e", "ld e,iyh", "ld e,iyl", "ld e,(iy+%hhd)", "ld e,a", "ld iyh,b", "ld iyh,c", "ld iyh,d", "ld iyh,e", "ld iyh,iyh", "ld iyh,iyl", "ld h,(iy+%hhd)", "ld iyh,a", "ld iyl,b", "ld iyl,c", "ld iyl,d", "ld iyl,e", "ld iyl,iyh", "ld iyl,iyl", "ld l,(iy+%hhd)", "ld iyl,a", "ld (iy+%hhd),b", "ld (iy+%hhd),c", "ld (iy+%hhd),d", "ld (iy+%hhd),e", "ld (iy+%hhd),h", "ld (iy+%hhd),l", "", "ld (iy+%hhd),a", "ld a,b", "ld a,c", "ld a,d", "ld a,e", "ld a,iyh", "ld a,iyl", "ld a,(iy+%hhd)", "ld a,a", "add a,b", "add a,c", "add a,d", "add a,e", "add a,iyh", "add a,iyl", "add a,(iy+%hhd)", "add a,a", "adc a,b", "adc a,c", "adc a,d", "adc a,e", "adc a,iyh", "adc a,iyl", "adc a,(iy+%hhd)", "adc a,a", "sub b", "sub c", "sub d", "sub e", "sub iyh", "sub iyl", "sub (iy+%hhd)", "sub a", "sbc a,b", "sbc a,c", "sbc a,d", "sbc a,e", "sbc a,iyh", "sbc a,iyl", "sbc a,(iy+%hhd)", "sbc a,a", "and b", "and c", "and d", "and e", "and iyh", "and iyl", "and (iy+%hhd)", "and a", "xor b", "xor c", "xor d", "xor e", "xor iyh", "xor iyl", "xor (iy+%hhd)", "xor a", "or b", "or c", "or d", "or e", "or iyh", "or iyl", "or (iy+%hhd)", "or a", "cp b", "cp c", "cp d", "cp e", "cp iyh", "cp iyl", "cp (iy+%hhd)", "cp a", "", "", "", "", "", "", "", "", "", "", "", "_IY Bit_", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "pop iy", "", "ex (sp),iy", "", "push iy", "", "", "", "jp (iy)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ld sp,iy", "", "", "", "", "", ""}; + const char *iy_bit_opcodes[256] = {"rlc (iy+%hhd),b", "rlc (iy+%hhd),c", "rlc (iy+%hhd),d", "rlc (iy+%hhd),e", "rlc (iy+%hhd),h", "rlc (iy+%hhd),l", "rlc (iy+%hhd)", "rlc (iy+%hhd),a", "rrc (iy+%hhd),b", "rrc (iy+%hhd),c", "rrc (iy+%hhd),d", "rrc (iy+%hhd),e", "rrc (iy+%hhd),h", "rrc (iy+%hhd),l", "rrc (iy+%hhd)", "rrc (iy+%hhd),a", "rl (iy+%hhd),b", "rl (iy+%hhd),c", "rl (iy+%hhd),d", "rl (iy+%hhd),e", "rl (iy+%hhd),h", "rl (iy+%hhd),l", "rl (iy+%hhd)", "rl (iy+%hhd),a", "rr (iy+%hhd),b", "rr (iy+%hhd),c", "rr (iy+%hhd),d", "rr (iy+%hhd),e", "rr (iy+%hhd),h", "rr (iy+%hhd),l", "rr (iy+%hhd)", "rr (iy+%hhd),a", "sla (iy+%hhd),b", "sla (iy+%hhd),c", "sla (iy+%hhd),d", "sla (iy+%hhd),e", "sla (iy+%hhd),h", "sla (iy+%hhd),l", "sla (iy+%hhd)", "sla (iy+%hhd),a", "sra (iy+%hhd),b", "sra (iy+%hhd),c", "sra (iy+%hhd),d", "sra (iy+%hhd),e", "sra (iy+%hhd),h", "sra (iy+%hhd),l", "sra (iy+%hhd)", "sra (iy+%hhd),a", "sll (iy+%hhd),b", "sll (iy+%hhd),c", "sll (iy+%hhd),d", "sll (iy+%hhd),e", "sll (iy+%hhd),h", "sll (iy+%hhd),l", "sll (iy+%hhd)", "sll (iy+%hhd),a", "srl (iy+%hhd),b", "srl (iy+%hhd),c", "srl (iy+%hhd),d", "srl (iy+%hhd),e", "srl (iy+%hhd),h", "srl (iy+%hhd),l", "srl (iy+%hhd)", "srl (iy+%hhd),a", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "res 0,(iy+%hhd),b", "res 0,(iy+%hhd),c", "res 0,(iy+%hhd),d", "res 0,(iy+%hhd),e", "res 0,(iy+%hhd),h", "res 0,(iy+%hhd),l", "res 0,(iy+%hhd)", "res 0,(iy+%hhd),a", "res 1,(iy+%hhd),b", "res 1,(iy+%hhd),c", "res 1,(iy+%hhd),d", "res 1,(iy+%hhd),e", "res 1,(iy+%hhd),h", "res 1,(iy+%hhd),l", "res 1,(iy+%hhd)", "res 1,(iy+%hhd),a", "res 2,(iy+%hhd),b", "res 2,(iy+%hhd),c", "res 2,(iy+%hhd),d", "res 2,(iy+%hhd),e", "res 2,(iy+%hhd),h", "res 2,(iy+%hhd),l", "res 2,(iy+%hhd)", "res 2,(iy+%hhd),a", "res 3,(iy+%hhd),b", "res 3,(iy+%hhd),c", "res 3,(iy+%hhd),d", "res 3,(iy+%hhd),e", "res 3,(iy+%hhd),h", "res 3,(iy+%hhd),l", "res 3,(iy+%hhd)", "res 3,(iy+%hhd),a", "res 4,(iy+%hhd),b", "res 4,(iy+%hhd),c", "res 4,(iy+%hhd),d", "res 4,(iy+%hhd),e", "res 4,(iy+%hhd),h", "res 4,(iy+%hhd),l", "res 4,(iy+%hhd)", "res 4,(iy+%hhd),a", "res 5,(iy+%hhd),b", "res 5,(iy+%hhd),c", "res 5,(iy+%hhd),d", "res 5,(iy+%hhd),e", "res 5,(iy+%hhd),h", "res 5,(iy+%hhd),l", "res 5,(iy+%hhd)", "res 5,(iy+%hhd),a", "res 6,(iy+%hhd),b", "res 6,(iy+%hhd),c", "res 6,(iy+%hhd),d", "res 6,(iy+%hhd),e", "res 6,(iy+%hhd),h", "res 6,(iy+%hhd),l", "res 6,(iy+%hhd)", "res 6,(iy+%hhd),a", "res 7,(iy+%hhd),b", "res 7,(iy+%hhd),c", "res 7,(iy+%hhd),d", "res 7,(iy+%hhd),e", "res 7,(iy+%hhd),h", "res 7,(iy+%hhd),l", "res 7,(iy+%hhd)", "res 7,(iy+%hhd),a", "set 0,(iy+%hhd),b", "set 0,(iy+%hhd),c", "set 0,(iy+%hhd),d", "set 0,(iy+%hhd),e", "set 0,(iy+%hhd),h", "set 0,(iy+%hhd),l", "set 0,(iy+%hhd)", "set 0,(iy+%hhd),a", "set 1,(iy+%hhd),b", "set 1,(iy+%hhd),c", "set 1,(iy+%hhd),d", "set 1,(iy+%hhd),e", "set 1,(iy+%hhd),h", "set 1,(iy+%hhd),l", "set 1,(iy+%hhd)", "set 1,(iy+%hhd),a", "set 2,(iy+%hhd),b", "set 2,(iy+%hhd),c", "set 2,(iy+%hhd),d", "set 2,(iy+%hhd),e", "set 2,(iy+%hhd),h", "set 2,(iy+%hhd),l", "set 2,(iy+%hhd)", "set 2,(iy+%hhd),a", "set 3,(iy+%hhd),b", "set 3,(iy+%hhd),c", "set 3,(iy+%hhd),d", "set 3,(iy+%hhd),e", "set 3,(iy+%hhd),h", "set 3,(iy+%hhd),l", "set 3,(iy+%hhd)", "set 3,(iy+%hhd),a", "set 4,(iy+%hhd),b", "set 4,(iy+%hhd),c", "set 4,(iy+%hhd),d", "set 4,(iy+%hhd),e", "set 4,(iy+%hhd),h", "set 4,(iy+%hhd),l", "set 4,(iy+%hhd)", "set 4,(iy+%hhd),a", "set 5,(iy+%hhd),b", "set 5,(iy+%hhd),c", "set 5,(iy+%hhd),d", "set 5,(iy+%hhd),e", "set 5,(iy+%hhd),h", "set 5,(iy+%hhd),l", "set 5,(iy+%hhd)", "set 5,(iy+%hhd),a", "set 6,(iy+%hhd),b", "set 6,(iy+%hhd),c", "set 6,(iy+%hhd),d", "set 6,(iy+%hhd),e", "set 6,(iy+%hhd),h", "set 6,(iy+%hhd),l", "set 6,(iy+%hhd)", "set 6,(iy+%hhd),a", "set 7,(iy+%hhd),b", "set 7,(iy+%hhd),c", "set 7,(iy+%hhd),d", "set 7,(iy+%hhd),e", "set 7,(iy+%hhd),h", "set 7,(iy+%hhd),l", "set 7,(iy+%hhd)", "set 7,(iy+%hhd),a"}; + +// const char *base_opcodes[256] = {"nop", "ld bc,$%04x", "ld (bc),a", "inc bc", "inc b", "dec b", "ld b,$%02x", "rlca", "ex af,af'", "add hl,bc", "ld a,(bc)", "dec bc", "inc c", "dec c", "ld c,$%02x", "rrca", "djnz %hhd", "ld de,$%04x", "ld (de),a", "inc de", "inc d", "dec d", "ld d,$%02x", "rla", "jr %hhd", "add hl,de", "ld a,(de)", "dec de", "inc e", "dec e", "ld e,$%02x", "rra", "jr nz,%hhd", "ld hl,$%04x", "ld ($%04x),hl", "inc hl", "inc h", "dec h", "ld h,$%02x", "daa", "jr z,%hhd", "add hl,hl", "ld hl,($%04x)", "dec hl", "inc l", "dec l", "ld l,$%02x", "cpl", "jr nc,%hhd", "ld sp,$%04x", "ld ($%04x),a", "inc sp", "inc (hl)", "dec (hl)", "ld (hl),$%02x", "scf", "jr c,%hhd", "add hl,sp", "ld a,($%04x)", "dec sp", "inc a", "dec a", "ld a,$%02x", "ccf", "ld b,b", "ld b,c", "ld b,d", "ld b,e", "ld b,h", "ld b,l", "ld b,(hl)", "ld b,a", "ld c,b", "ld c,c", "ld c,d", "ld c,e", "ld c,h", "ld c,l", "ld c,(hl)", "ld c,a", "ld d,b", "ld d,c", "ld d,d", "ld d,e", "ld d,h", "ld d,l", "ld d,(hl)", "ld d,a", "ld e,b", "ld e,c", "ld e,d", "ld e,e", "ld e,h", "ld e,l", "ld e,(hl)", "ld e,a", "ld h,b", "ld h,c", "ld h,d", "ld h,e", "ld h,h", "ld h,l", "ld h,(hl)", "ld h,a", "ld l,b", "ld l,c", "ld l,d", "ld l,e", "ld l,h", "ld l,l", "ld l,(hl)", "ld l,a", "ld (hl),b", "ld (hl),c", "ld (hl),d", "ld (hl),e", "ld (hl),h", "ld (hl),l", "halt", "ld (hl),a", "ld a,b", "ld a,c", "ld a,d", "ld a,e", "ld a,h", "ld a,l", "ld a,(hl)", "ld a,a", "add a,b", "add a,c", "add a,d", "add a,e", "add a,h", "add a,l", "add a,(hl)", "add a,a", "adc a,b", "adc a,c", "adc a,d", "adc a,e", "adc a,h", "adc a,l", "adc a,(hl)", "adc a,a", "sub b", "sub c", "sub d", "sub e", "sub h", "sub l", "sub (hl)", "sub a", "sbc a,b", "sbc a,c", "sbc a,d", "sbc a,e", "sbc a,h", "sbc a,l", "sbc a,(hl)", "sbc a,a", "and b", "and c", "and d", "and e", "and h", "and l", "and (hl)", "and a", "xor b", "xor c", "xor d", "xor e", "xor h", "xor l", "xor (hl)", "xor a", "or b", "or c", "or d", "or e", "or h", "or l", "or (hl)", "or a", "cp b", "cp c", "cp d", "cp e", "cp h", "cp l", "cp (hl)", "cp a", "ret nz", "pop bc", "jp nz,$%04x", "jp $%04x", "call nz,$%04x", "push bc", "add a,$%02x", "rst 00h", "ret z", "ret", "jp z,$%04x", "_Bit_", "call z,$%04x", "call $%04x", "adc a,$%02x", "rst 08h", "ret nc", "pop de", "jp nc,$%04x", "out ($%02x),a", "call nc,$%04x", "push de", "sub $%02x", "rst 10h", "ret c", "exx", "jp c,$%04x", "in a,($%02x)", "call c,$%04x", "_IX_", "sbc a,$%02x", "rst 18h", "ret po", "pop hl", "jp po,$%04x", "ex (sp),hl", "call po,$%04x", "push hl", "and $%02x", "rst 20h", "ret pe", "jp (hl)", "jp pe,$%04x", "ex de,hl", "call pe,$%04x", "_Misc._", "xor $%02x", "rst 28h", "ret p", "pop af", "jp p,$%04x", "di", "call p,$%04x", "push af", "or $%02x", "rst 30h", "ret m", "ld sp,hl", "jp m,$%04x", "ei", "call m,$%04x", "_IY_", "cp $%02x", "rst 38h"}; +// const char *cb_opcodes[256] = {"rlc b", "rlc c", "rlc d", "rlc e", "rlc h", "rlc l", "rlc (hl)", "rlc a", "rrc b", "rrc c", "rrc d", "rrc e", "rrc h", "rrc l", "rrc (hl)", "rrc a", "rl b", "rl c", "rl d", "rl e", "rl h", "rl l", "rl (hl)", "rl a", "rr b", "rr c", "rr d", "rr e", "rr h", "rr l", "rr (hl)", "rr a", "sla b", "sla c", "sla d", "sla e", "sla h", "sla l", "sla (hl)", "sla a", "sra b", "sra c", "sra d", "sra e", "sra h", "sra l", "sra (hl)", "sra a", "sll b", "sll c", "sll d", "sll e", "sll h", "sll l", "sll (hl)", "sll a", "srl b", "srl c", "srl d", "srl e", "srl h", "srl l", "srl (hl)", "srl a", "bit 0,b", "bit 0,c", "bit 0,d", "bit 0,e", "bit 0,h", "bit 0,l", "bit 0,(hl)", "bit 0,a", "bit 1,b", "bit 1,c", "bit 1,d", "bit 1,e", "bit 1,h", "bit 1,l", "bit 1,(hl)", "bit 1,a", "bit 2,b", "bit 2,c", "bit 2,d", "bit 2,e", "bit 2,h", "bit 2,l", "bit 2,(hl)", "bit 2,a", "bit 3,b", "bit 3,c", "bit 3,d", "bit 3,e", "bit 3,h", "bit 3,l", "bit 3,(hl)", "bit 3,a", "bit 4,b", "bit 4,c", "bit 4,d", "bit 4,e", "bit 4,h", "bit 4,l", "bit 4,(hl)", "bit 4,a", "bit 5,b", "bit 5,c", "bit 5,d", "bit 5,e", "bit 5,h", "bit 5,l", "bit 5,(hl)", "bit 5,a", "bit 6,b", "bit 6,c", "bit 6,d", "bit 6,e", "bit 6,h", "bit 6,l", "bit 6,(hl)", "bit 6,a", "bit 7,b", "bit 7,c", "bit 7,d", "bit 7,e", "bit 7,h", "bit 7,l", "bit 7,(hl)", "bit 7,a", "res 0,b", "res 0,c", "res 0,d", "res 0,e", "res 0,h", "res 0,l", "res 0,(hl)", "res 0,a", "res 1,b", "res 1,c", "res 1,d", "res 1,e", "res 1,h", "res 1,l", "res 1,(hl)", "res 1,a", "res 2,b", "res 2,c", "res 2,d", "res 2,e", "res 2,h", "res 2,l", "res 2,(hl)", "res 2,a", "res 3,b", "res 3,c", "res 3,d", "res 3,e", "res 3,h", "res 3,l", "res 3,(hl)", "res 3,a", "res 4,b", "res 4,c", "res 4,d", "res 4,e", "res 4,h", "res 4,l", "res 4,(hl)", "res 4,a", "res 5,b", "res 5,c", "res 5,d", "res 5,e", "res 5,h", "res 5,l", "res 5,(hl)", "res 5,a", "res 6,b", "res 6,c", "res 6,d", "res 6,e", "res 6,h", "res 6,l", "res 6,(hl)", "res 6,a", "res 7,b", "res 7,c", "res 7,d", "res 7,e", "res 7,h", "res 7,l", "res 7,(hl)", "res 7,a", "set 0,b", "set 0,c", "set 0,d", "set 0,e", "set 0,h", "set 0,l", "set 0,(hl)", "set 0,a", "set 1,b", "set 1,c", "set 1,d", "set 1,e", "set 1,h", "set 1,l", "set 1,(hl)", "set 1,a", "set 2,b", "set 2,c", "set 2,d", "set 2,e", "set 2,h", "set 2,l", "set 2,(hl)", "set 2,a", "set 3,b", "set 3,c", "set 3,d", "set 3,e", "set 3,h", "set 3,l", "set 3,(hl)", "set 3,a", "set 4,b", "set 4,c", "set 4,d", "set 4,e", "set 4,h", "set 4,l", "set 4,(hl)", "set 4,a", "set 5,b", "set 5,c", "set 5,d", "set 5,e", "set 5,h", "set 5,l", "set 5,(hl)", "set 5,a", "set 6,b", "set 6,c", "set 6,d", "set 6,e", "set 6,h", "set 6,l", "set 6,(hl)", "set 6,a", "set 7,b", "set 7,c", "set 7,d", "set 7,e", "set 7,h", "set 7,l", "set 7,(hl)", "set 7,a"}; +// const char *ix_opcodes[256] = {"", "", "", "", "inc b", "dec b", "ld b,$%02x", "", "", "add ix,bc", "", "", "inc c", "dec c", "ld c,$%02x", "", "", "", "", "", "inc d", "dec d", "ld d,$%02x", "", "", "add ix,de", "", "", "inc e", "dec e", "ld e,$%02x", "", "", "ld ix,$%04x", "ld ($%04x),ix", "inc ix", "inc ixh", "dec ixh", "ld ixh,$%02x", "", "", "add ix,ix", "ld ix,($%04x)", "dec ix", "inc ixl", "dec ixl", "ld ixl,$%02x", "", "", "", "", "", "inc (ix+%hhd)", "dec (ix+%hhd)", "ld (ix+%hhd),$%02x", "", "", "add ix,sp", "", "", "inc a", "dec a", "ld a,$%02x", "", "ld b,b", "ld b,c", "ld b,d", "ld b,e", "ld b,ixh", "ld b,ixl", "ld b,(ix+%hhd)", "ld b,a", "ld c,b", "ld c,c", "ld c,d", "ld c,e", "ld c,ixh", "ld c,ixl", "ld c,(ix+%hhd)", "ld c,a", "ld d,b", "ld d,c", "ld d,d", "ld d,e", "ld d,ixh", "ld d,ixl", "ld d,(ix+%hhd)", "ld d,a", "ld e,b", "ld e,c", "ld e,d", "ld e,e", "ld e,ixh", "ld e,ixl", "ld e,(ix+%hhd)", "ld e,a", "ld ixh,b", "ld ixh,c", "ld ixh,d", "ld ixh,e", "ld ixh,ixh", "ld ixh,ixl", "ld h,(ix+%hhd)", "ld ixh,a", "ld ixl,b", "ld ixl,c", "ld ixl,d", "ld ixl,e", "ld ixl,ixh", "ld ixl,ixl", "ld l,(ix+%hhd)", "ld ixl,a", "ld (ix+%hhd),b", "ld (ix+%hhd),c", "ld (ix+%hhd),d", "ld (ix+%hhd),e", "ld (ix+%hhd),h", "ld (ix+%hhd),l", "", "ld (ix+%hhd),a", "ld a,b", "ld a,c", "ld a,d", "ld a,e", "ld a,ixh", "ld a,ixl", "ld a,(ix+%hhd)", "ld a,a", "add a,b", "add a,c", "add a,d", "add a,e", "add a,ixh", "add a,ixl", "add a,(ix+%hhd)", "add a,a", "adc a,b", "adc a,c", "adc a,d", "adc a,e", "adc a,ixh", "adc a,ixl", "adc a,(ix+%hhd)", "adc a,a", "sub b", "sub c", "sub d", "sub e", "sub ixh", "sub ixl", "sub (ix+%hhd)", "sub a", "sbc a,b", "sbc a,c", "sbc a,d", "sbc a,e", "sbc a,ixh", "sbc a,ixl", "sbc a,(ix+%hhd)", "sbc a,a", "and b", "and c", "and d", "and e", "and ixh", "and ixl", "and (ix+%hhd)", "and a", "xor b", "xor c", "xor d", "xor e", "xor ixh", "xor ixl", "xor (ix+%hhd)", "xor a", "or b", "or c", "or d", "or e", "or ixh", "or ixl", "or (ix+%hhd)", "or a", "cp b", "cp c", "cp d", "cp e", "cp ixh", "cp ixl", "cp (ix+%hhd)", "cp a", "", "", "", "", "", "", "", "", "", "", "", "_IX Bit_", "", "", "", "", "", "pop ix", "", "ex (sp),ix", "", "push ix", "", "", "", "jp (ix)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ld sp,ix", "", "", "", "", "", ""}; +// const char *ix_bit_opcodes[256] = {"rlc (ix+%hhd),b", "rlc (ix+%hhd),c", "rlc (ix+%hhd),d", "rlc (ix+%hhd),e", "rlc (ix+%hhd),h", "rlc (ix+%hhd),l", "rlc (ix+%hhd)", "rlc (ix+%hhd),a", "rrc (ix+%hhd),b", "rrc (ix+%hhd),c", "rrc (ix+%hhd),d", "rrc (ix+%hhd),e", "rrc (ix+%hhd),h", "rrc (ix+%hhd),l", "rrc (ix+%hhd)", "rrc (ix+%hhd),a", "rl (ix+%hhd),b", "rl (ix+%hhd),c", "rl (ix+%hhd),d", "rl (ix+%hhd),e", "rl (ix+%hhd),h", "rl (ix+%hhd),l", "rl (ix+%hhd)", "rl (ix+%hhd),a", "rr (ix+%hhd),b", "rr (ix+%hhd),c", "rr (ix+%hhd),d", "rr (ix+%hhd),e", "rr (ix+%hhd),h", "rr (ix+%hhd),l", "rr (ix+%hhd)", "rr (ix+%hhd),a", "sla (ix+%hhd),b", "sla (ix+%hhd),c", "sla (ix+%hhd),d", "sla (ix+%hhd),e", "sla (ix+%hhd),h", "sla (ix+%hhd),l", "sla (ix+%hhd)", "sla (ix+%hhd),a", "sra (ix+%hhd),b", "sra (ix+%hhd),c", "sra (ix+%hhd),d", "sra (ix+%hhd),e", "sra (ix+%hhd),h", "sra (ix+%hhd),l", "sra (ix+%hhd)", "sra (ix+%hhd),a", "sll (ix+%hhd),b", "sll (ix+%hhd),c", "sll (ix+%hhd),d", "sll (ix+%hhd),e", "sll (ix+%hhd),h", "sll (ix+%hhd),l", "sll (ix+%hhd)", "sll (ix+%hhd),a", "srl (ix+%hhd),b", "srl (ix+%hhd),c", "srl (ix+%hhd),d", "srl (ix+%hhd),e", "srl (ix+%hhd),h", "srl (ix+%hhd),l", "srl (ix+%hhd)", "srl (ix+%hhd),a", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 0,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 1,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 2,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 3,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 4,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 5,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 6,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "bit 7,(ix+%hhd)", "res 0,(ix+%hhd),b", "res 0,(ix+%hhd),c", "res 0,(ix+%hhd),d", "res 0,(ix+%hhd),e", "res 0,(ix+%hhd),h", "res 0,(ix+%hhd),l", "res 0,(ix+%hhd)", "res 0,(ix+%hhd),a", "res 1,(ix+%hhd),b", "res 1,(ix+%hhd),c", "res 1,(ix+%hhd),d", "res 1,(ix+%hhd),e", "res 1,(ix+%hhd),h", "res 1,(ix+%hhd),l", "res 1,(ix+%hhd)", "res 1,(ix+%hhd),a", "res 2,(ix+%hhd),b", "res 2,(ix+%hhd),c", "res 2,(ix+%hhd),d", "res 2,(ix+%hhd),e", "res 2,(ix+%hhd),h", "res 2,(ix+%hhd),l", "res 2,(ix+%hhd)", "res 2,(ix+%hhd),a", "res 3,(ix+%hhd),b", "res 3,(ix+%hhd),c", "res 3,(ix+%hhd),d", "res 3,(ix+%hhd),e", "res 3,(ix+%hhd),h", "res 3,(ix+%hhd),l", "res 3,(ix+%hhd)", "res 3,(ix+%hhd),a", "res 4,(ix+%hhd),b", "res 4,(ix+%hhd),c", "res 4,(ix+%hhd),d", "res 4,(ix+%hhd),e", "res 4,(ix+%hhd),h", "res 4,(ix+%hhd),l", "res 4,(ix+%hhd)", "res 4,(ix+%hhd),a", "res 5,(ix+%hhd),b", "res 5,(ix+%hhd),c", "res 5,(ix+%hhd),d", "res 5,(ix+%hhd),e", "res 5,(ix+%hhd),h", "res 5,(ix+%hhd),l", "res 5,(ix+%hhd)", "res 5,(ix+%hhd),a", "res 6,(ix+%hhd),b", "res 6,(ix+%hhd),c", "res 6,(ix+%hhd),d", "res 6,(ix+%hhd),e", "res 6,(ix+%hhd),h", "res 6,(ix+%hhd),l", "res 6,(ix+%hhd)", "res 6,(ix+%hhd),a", "res 7,(ix+%hhd),b", "res 7,(ix+%hhd),c", "res 7,(ix+%hhd),d", "res 7,(ix+%hhd),e", "res 7,(ix+%hhd),h", "res 7,(ix+%hhd),l", "res 7,(ix+%hhd)", "res 7,(ix+%hhd),a", "set 0,(ix+%hhd),b", "set 0,(ix+%hhd),c", "set 0,(ix+%hhd),d", "set 0,(ix+%hhd),e", "set 0,(ix+%hhd),h", "set 0,(ix+%hhd),l", "set 0,(ix+%hhd)", "set 0,(ix+%hhd),a", "set 1,(ix+%hhd),b", "set 1,(ix+%hhd),c", "set 1,(ix+%hhd),d", "set 1,(ix+%hhd),e", "set 1,(ix+%hhd),h", "set 1,(ix+%hhd),l", "set 1,(ix+%hhd)", "set 1,(ix+%hhd),a", "set 2,(ix+%hhd),b", "set 2,(ix+%hhd),c", "set 2,(ix+%hhd),d", "set 2,(ix+%hhd),e", "set 2,(ix+%hhd),h", "set 2,(ix+%hhd),l", "set 2,(ix+%hhd)", "set 2,(ix+%hhd),a", "set 3,(ix+%hhd),b", "set 3,(ix+%hhd),c", "set 3,(ix+%hhd),d", "set 3,(ix+%hhd),e", "set 3,(ix+%hhd),h", "set 3,(ix+%hhd),l", "set 3,(ix+%hhd)", "set 3,(ix+%hhd),a", "set 4,(ix+%hhd),b", "set 4,(ix+%hhd),c", "set 4,(ix+%hhd),d", "set 4,(ix+%hhd),e", "set 4,(ix+%hhd),h", "set 4,(ix+%hhd),l", "set 4,(ix+%hhd)", "set 4,(ix+%hhd),a", "set 5,(ix+%hhd),b", "set 5,(ix+%hhd),c", "set 5,(ix+%hhd),d", "set 5,(ix+%hhd),e", "set 5,(ix+%hhd),h", "set 5,(ix+%hhd),l", "set 5,(ix+%hhd)", "set 5,(ix+%hhd),a", "set 6,(ix+%hhd),b", "set 6,(ix+%hhd),c", "set 6,(ix+%hhd),d", "set 6,(ix+%hhd),e", "set 6,(ix+%hhd),h", "set 6,(ix+%hhd),l", "set 6,(ix+%hhd)", "set 6,(ix+%hhd),a", "set 7,(ix+%hhd),b", "set 7,(ix+%hhd),c", "set 7,(ix+%hhd),d", "set 7,(ix+%hhd),e", "set 7,(ix+%hhd),h", "set 7,(ix+%hhd),l", "set 7,(ix+%hhd)", "set 7,(ix+%hhd),a"}; +// const char *misc_opcodes[128] = {"in b,(c)", "out (c),b", "sbc hl,bc", "ld ($%04x),bc", "neg", "retn", "im 0", "ld i,a", "in c,(c)", "out (c),c", "adc hl,bc", "ld bc,($%04x)", "mlt bc", "reti", "", "ld r,a", "in d,(c)", "out (c),d", "sbc hl,de", "ld ($%04x),de", "", "", "im 1", "ld a,i", "in e,(c)", "out (c),e", "adc hl,de", "ld de,($%04x)", "mlt de", "", "im 2", "ld a,r", "in h,(c)", "out (c),h", "sbc hl,hl", "ld ($%04x),hl", "tst $%02x", "", "", "rrd", "in l,(c)", "out (c),l", "adc hl,hl", "ld hl,($%04x)", "mlt hl", "", "", "rld", "in (c)", "out (c),0", "sbc hl,sp", "ld ($%04x),sp", "tstio $%02x", "", "slp", "", "in a,(c)", "out (c),a", "adc hl,sp", "ld sp,($%04x)", "mlt sp", "", "", "", "", "", "", "otim", "", "", "", "", "", "", "", "otdm", "", "", "", "", "", "", "", "otimr", "", "", "", "", "", "", "", "otdmr", "", "", "", "", "ldi", "cpi", "ini", "outi", "", "", "", "", "ldd", "cpd", "ind", "outd", "", "", "", "", "ldir", "cpir", "inir", "otir", "", "", "", "", "lddr", "cpdr", "indr", "otdr", "", "", "", ""}; +// const char *iy_opcodes[256] = {"", "", "", "", "inc b", "dec b", "ld b,$%02x", "", "", "add iy,bc", "", "", "inc c", "dec c", "ld c,$%02x", "", "", "", "", "", "inc d", "dec d", "ld d,$%02x", "", "", "add iy,de", "", "", "inc e", "dec e", "ld e,$%02x", "", "", "ld iy,$%04x", "ld ($%04x),iy", "inc iy", "inc iyh", "dec iyh", "ld iyh,$%02x", "", "", "add iy,iy", "ld iy,($%04x)", "dec iy", "inc iyl", "dec iyl", "ld iyl,$%02x", "", "", "", "", "", "inc (iy+%hhd)", "dec (iy+%hhd)", "ld (iy+%hhd),$%02x", "", "", "add iy,sp", "", "", "inc a", "dec a", "ld a,$%02x", "", "ld b,b", "ld b,c", "ld b,d", "ld b,e", "ld b,iyh", "ld b,iyl", "ld b,(iy+%hhd)", "ld b,a", "ld c,b", "ld c,c", "ld c,d", "ld c,e", "ld c,iyh", "ld c,iyl", "ld c,(iy+%hhd)", "ld c,a", "ld d,b", "ld d,c", "ld d,d", "ld d,e", "ld d,iyh", "ld d,iyl", "ld d,(iy+%hhd)", "ld d,a", "ld e,b", "ld e,c", "ld e,d", "ld e,e", "ld e,iyh", "ld e,iyl", "ld e,(iy+%hhd)", "ld e,a", "ld iyh,b", "ld iyh,c", "ld iyh,d", "ld iyh,e", "ld iyh,iyh", "ld iyh,iyl", "ld h,(iy+%hhd)", "ld iyh,a", "ld iyl,b", "ld iyl,c", "ld iyl,d", "ld iyl,e", "ld iyl,iyh", "ld iyl,iyl", "ld l,(iy+%hhd)", "ld iyl,a", "ld (iy+%hhd),b", "ld (iy+%hhd),c", "ld (iy+%hhd),d", "ld (iy+%hhd),e", "ld (iy+%hhd),h", "ld (iy+%hhd),l", "", "ld (iy+%hhd),a", "ld a,b", "ld a,c", "ld a,d", "ld a,e", "ld a,iyh", "ld a,iyl", "ld a,(iy+%hhd)", "ld a,a", "add a,b", "add a,c", "add a,d", "add a,e", "add a,iyh", "add a,iyl", "add a,(iy+%hhd)", "add a,a", "adc a,b", "adc a,c", "adc a,d", "adc a,e", "adc a,iyh", "adc a,iyl", "adc a,(iy+%hhd)", "adc a,a", "sub b", "sub c", "sub d", "sub e", "sub iyh", "sub iyl", "sub (iy+%hhd)", "sub a", "sbc a,b", "sbc a,c", "sbc a,d", "sbc a,e", "sbc a,iyh", "sbc a,iyl", "sbc a,(iy+%hhd)", "sbc a,a", "and b", "and c", "and d", "and e", "and iyh", "and iyl", "and (iy+%hhd)", "and a", "xor b", "xor c", "xor d", "xor e", "xor iyh", "xor iyl", "xor (iy+%hhd)", "xor a", "or b", "or c", "or d", "or e", "or iyh", "or iyl", "or (iy+%hhd)", "or a", "cp b", "cp c", "cp d", "cp e", "cp iyh", "cp iyl", "cp (iy+%hhd)", "cp a", "", "", "", "", "", "", "", "", "", "", "", "_IY Bit_", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "pop iy", "", "ex (sp),iy", "", "push iy", "", "", "", "jp (iy)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ld sp,iy", "", "", "", "", "", ""}; +// const char *iy_bit_opcodes[256] = {"rlc (iy+%hhd),b", "rlc (iy+%hhd),c", "rlc (iy+%hhd),d", "rlc (iy+%hhd),e", "rlc (iy+%hhd),h", "rlc (iy+%hhd),l", "rlc (iy+%hhd)", "rlc (iy+%hhd),a", "rrc (iy+%hhd),b", "rrc (iy+%hhd),c", "rrc (iy+%hhd),d", "rrc (iy+%hhd),e", "rrc (iy+%hhd),h", "rrc (iy+%hhd),l", "rrc (iy+%hhd)", "rrc (iy+%hhd),a", "rl (iy+%hhd),b", "rl (iy+%hhd),c", "rl (iy+%hhd),d", "rl (iy+%hhd),e", "rl (iy+%hhd),h", "rl (iy+%hhd),l", "rl (iy+%hhd)", "rl (iy+%hhd),a", "rr (iy+%hhd),b", "rr (iy+%hhd),c", "rr (iy+%hhd),d", "rr (iy+%hhd),e", "rr (iy+%hhd),h", "rr (iy+%hhd),l", "rr (iy+%hhd)", "rr (iy+%hhd),a", "sla (iy+%hhd),b", "sla (iy+%hhd),c", "sla (iy+%hhd),d", "sla (iy+%hhd),e", "sla (iy+%hhd),h", "sla (iy+%hhd),l", "sla (iy+%hhd)", "sla (iy+%hhd),a", "sra (iy+%hhd),b", "sra (iy+%hhd),c", "sra (iy+%hhd),d", "sra (iy+%hhd),e", "sra (iy+%hhd),h", "sra (iy+%hhd),l", "sra (iy+%hhd)", "sra (iy+%hhd),a", "sll (iy+%hhd),b", "sll (iy+%hhd),c", "sll (iy+%hhd),d", "sll (iy+%hhd),e", "sll (iy+%hhd),h", "sll (iy+%hhd),l", "sll (iy+%hhd)", "sll (iy+%hhd),a", "srl (iy+%hhd),b", "srl (iy+%hhd),c", "srl (iy+%hhd),d", "srl (iy+%hhd),e", "srl (iy+%hhd),h", "srl (iy+%hhd),l", "srl (iy+%hhd)", "srl (iy+%hhd),a", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 0,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 1,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 2,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 3,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 4,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 5,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 6,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "bit 7,(iy+%hhd)", "res 0,(iy+%hhd),b", "res 0,(iy+%hhd),c", "res 0,(iy+%hhd),d", "res 0,(iy+%hhd),e", "res 0,(iy+%hhd),h", "res 0,(iy+%hhd),l", "res 0,(iy+%hhd)", "res 0,(iy+%hhd),a", "res 1,(iy+%hhd),b", "res 1,(iy+%hhd),c", "res 1,(iy+%hhd),d", "res 1,(iy+%hhd),e", "res 1,(iy+%hhd),h", "res 1,(iy+%hhd),l", "res 1,(iy+%hhd)", "res 1,(iy+%hhd),a", "res 2,(iy+%hhd),b", "res 2,(iy+%hhd),c", "res 2,(iy+%hhd),d", "res 2,(iy+%hhd),e", "res 2,(iy+%hhd),h", "res 2,(iy+%hhd),l", "res 2,(iy+%hhd)", "res 2,(iy+%hhd),a", "res 3,(iy+%hhd),b", "res 3,(iy+%hhd),c", "res 3,(iy+%hhd),d", "res 3,(iy+%hhd),e", "res 3,(iy+%hhd),h", "res 3,(iy+%hhd),l", "res 3,(iy+%hhd)", "res 3,(iy+%hhd),a", "res 4,(iy+%hhd),b", "res 4,(iy+%hhd),c", "res 4,(iy+%hhd),d", "res 4,(iy+%hhd),e", "res 4,(iy+%hhd),h", "res 4,(iy+%hhd),l", "res 4,(iy+%hhd)", "res 4,(iy+%hhd),a", "res 5,(iy+%hhd),b", "res 5,(iy+%hhd),c", "res 5,(iy+%hhd),d", "res 5,(iy+%hhd),e", "res 5,(iy+%hhd),h", "res 5,(iy+%hhd),l", "res 5,(iy+%hhd)", "res 5,(iy+%hhd),a", "res 6,(iy+%hhd),b", "res 6,(iy+%hhd),c", "res 6,(iy+%hhd),d", "res 6,(iy+%hhd),e", "res 6,(iy+%hhd),h", "res 6,(iy+%hhd),l", "res 6,(iy+%hhd)", "res 6,(iy+%hhd),a", "res 7,(iy+%hhd),b", "res 7,(iy+%hhd),c", "res 7,(iy+%hhd),d", "res 7,(iy+%hhd),e", "res 7,(iy+%hhd),h", "res 7,(iy+%hhd),l", "res 7,(iy+%hhd)", "res 7,(iy+%hhd),a", "set 0,(iy+%hhd),b", "set 0,(iy+%hhd),c", "set 0,(iy+%hhd),d", "set 0,(iy+%hhd),e", "set 0,(iy+%hhd),h", "set 0,(iy+%hhd),l", "set 0,(iy+%hhd)", "set 0,(iy+%hhd),a", "set 1,(iy+%hhd),b", "set 1,(iy+%hhd),c", "set 1,(iy+%hhd),d", "set 1,(iy+%hhd),e", "set 1,(iy+%hhd),h", "set 1,(iy+%hhd),l", "set 1,(iy+%hhd)", "set 1,(iy+%hhd),a", "set 2,(iy+%hhd),b", "set 2,(iy+%hhd),c", "set 2,(iy+%hhd),d", "set 2,(iy+%hhd),e", "set 2,(iy+%hhd),h", "set 2,(iy+%hhd),l", "set 2,(iy+%hhd)", "set 2,(iy+%hhd),a", "set 3,(iy+%hhd),b", "set 3,(iy+%hhd),c", "set 3,(iy+%hhd),d", "set 3,(iy+%hhd),e", "set 3,(iy+%hhd),h", "set 3,(iy+%hhd),l", "set 3,(iy+%hhd)", "set 3,(iy+%hhd),a", "set 4,(iy+%hhd),b", "set 4,(iy+%hhd),c", "set 4,(iy+%hhd),d", "set 4,(iy+%hhd),e", "set 4,(iy+%hhd),h", "set 4,(iy+%hhd),l", "set 4,(iy+%hhd)", "set 4,(iy+%hhd),a", "set 5,(iy+%hhd),b", "set 5,(iy+%hhd),c", "set 5,(iy+%hhd),d", "set 5,(iy+%hhd),e", "set 5,(iy+%hhd),h", "set 5,(iy+%hhd),l", "set 5,(iy+%hhd)", "set 5,(iy+%hhd),a", "set 6,(iy+%hhd),b", "set 6,(iy+%hhd),c", "set 6,(iy+%hhd),d", "set 6,(iy+%hhd),e", "set 6,(iy+%hhd),h", "set 6,(iy+%hhd),l", "set 6,(iy+%hhd)", "set 6,(iy+%hhd),a", "set 7,(iy+%hhd),b", "set 7,(iy+%hhd),c", "set 7,(iy+%hhd),d", "set 7,(iy+%hhd),e", "set 7,(iy+%hhd),h", "set 7,(iy+%hhd),l", "set 7,(iy+%hhd)", "set 7,(iy+%hhd),a"}; + +// const char *base_opcodes[256] = {"nop", "ld bc,NN", "ld (bc),a", "inc bc", "inc b", "dec b", "ld b,N", "rlca", "ex af,af'", "add hl,bc", "ld a,(bc)", "dec bc", "inc c", "dec c", "ld c,N", "rrca", "djnz D", "ld de,NN", "ld (de),a", "inc de", "inc d", "dec d", "ld d,N", "rla", "jr D", "add hl,de", "ld a,(de)", "dec de", "inc e", "dec e", "ld e,N", "rra", "jr nz,D", "ld hl,NN", "ld (NN),hl", "inc hl", "inc h", "dec h", "ld h,N", "daa", "jr z,D", "add hl,hl", "ld hl,(NN)", "dec hl", "inc l", "dec l", "ld l,N", "cpl", "jr nc,D", "ld sp,NN", "ld (NN),a", "inc sp", "inc (hl)", "dec (hl)", "ld (hl),N", "scf", "jr c,D", "add hl,sp", "ld a,(NN)", "dec sp", "inc a", "dec a", "ld a,N", "ccf", "ld b,b", "ld b,c", "ld b,d", "ld b,e", "ld b,h", "ld b,l", "ld b,(hl)", "ld b,a", "ld c,b", "ld c,c", "ld c,d", "ld c,e", "ld c,h", "ld c,l", "ld c,(hl)", "ld c,a", "ld d,b", "ld d,c", "ld d,d", "ld d,e", "ld d,h", "ld d,l", "ld d,(hl)", "ld d,a", "ld e,b", "ld e,c", "ld e,d", "ld e,e", "ld e,h", "ld e,l", "ld e,(hl)", "ld e,a", "ld h,b", "ld h,c", "ld h,d", "ld h,e", "ld h,h", "ld h,l", "ld h,(hl)", "ld h,a", "ld l,b", "ld l,c", "ld l,d", "ld l,e", "ld l,h", "ld l,l", "ld l,(hl)", "ld l,a", "ld (hl),b", "ld (hl),c", "ld (hl),d", "ld (hl),e", "ld (hl),h", "ld (hl),l", "halt", "ld (hl),a", "ld a,b", "ld a,c", "ld a,d", "ld a,e", "ld a,h", "ld a,l", "ld a,(hl)", "ld a,a", "add a,b", "add a,c", "add a,d", "add a,e", "add a,h", "add a,l", "add a,(hl)", "add a,a", "adc a,b", "adc a,c", "adc a,d", "adc a,e", "adc a,h", "adc a,l", "adc a,(hl)", "adc a,a", "sub b", "sub c", "sub d", "sub e", "sub h", "sub l", "sub (hl)", "sub a", "sbc a,b", "sbc a,c", "sbc a,d", "sbc a,e", "sbc a,h", "sbc a,l", "sbc a,(hl)", "sbc a,a", "and b", "and c", "and d", "and e", "and h", "and l", "and (hl)", "and a", "xor b", "xor c", "xor d", "xor e", "xor h", "xor l", "xor (hl)", "xor a", "or b", "or c", "or d", "or e", "or h", "or l", "or (hl)", "or a", "cp b", "cp c", "cp d", "cp e", "cp h", "cp l", "cp (hl)", "cp a", "ret nz", "pop bc", "jp nz,NN", "jp NN", "call nz,NN", "push bc", "add a,N", "rst 00h", "ret z", "ret", "jp z,NN", "_Bit_", "call z,NN", "call NN", "adc a,N", "rst 08h", "ret nc", "pop de", "jp nc,NN", "out (N),a", "call nc,NN", "push de", "sub N", "rst 10h", "ret c", "exx", "jp c,NN", "in a,(N)", "call c,NN", "_IX_", "sbc a,N", "rst 18h", "ret po", "pop hl", "jp po,NN", "ex (sp),hl", "call po,NN", "push hl", "and N", "rst 20h", "ret pe", "jp (hl)", "jp pe,NN", "ex de,hl", "call pe,NN", "_Misc._", "xor N", "rst 28h", "ret p", "pop af", "jp p,NN", "di", "call p,NN", "push af", "or N", "rst 30h", "ret m", "ld sp,hl", "jp m,NN", "ei", "call m,NN", "_IY_", "cp N", "rst 38h"}; +// const char *cb_opcodes[256] = {"rlc b", "rlc c", "rlc d", "rlc e", "rlc h", "rlc l", "rlc (hl)", "rlc a", "rrc b", "rrc c", "rrc d", "rrc e", "rrc h", "rrc l", "rrc (hl)", "rrc a", "rl b", "rl c", "rl d", "rl e", "rl h", "rl l", "rl (hl)", "rl a", "rr b", "rr c", "rr d", "rr e", "rr h", "rr l", "rr (hl)", "rr a", "sla b", "sla c", "sla d", "sla e", "sla h", "sla l", "sla (hl)", "sla a", "sra b", "sra c", "sra d", "sra e", "sra h", "sra l", "sra (hl)", "sra a", "sll b", "sll c", "sll d", "sll e", "sll h", "sll l", "sll (hl)", "sll a", "srl b", "srl c", "srl d", "srl e", "srl h", "srl l", "srl (hl)", "srl a", "bit 0,b", "bit 0,c", "bit 0,d", "bit 0,e", "bit 0,h", "bit 0,l", "bit 0,(hl)", "bit 0,a", "bit 1,b", "bit 1,c", "bit 1,d", "bit 1,e", "bit 1,h", "bit 1,l", "bit 1,(hl)", "bit 1,a", "bit 2,b", "bit 2,c", "bit 2,d", "bit 2,e", "bit 2,h", "bit 2,l", "bit 2,(hl)", "bit 2,a", "bit 3,b", "bit 3,c", "bit 3,d", "bit 3,e", "bit 3,h", "bit 3,l", "bit 3,(hl)", "bit 3,a", "bit 4,b", "bit 4,c", "bit 4,d", "bit 4,e", "bit 4,h", "bit 4,l", "bit 4,(hl)", "bit 4,a", "bit 5,b", "bit 5,c", "bit 5,d", "bit 5,e", "bit 5,h", "bit 5,l", "bit 5,(hl)", "bit 5,a", "bit 6,b", "bit 6,c", "bit 6,d", "bit 6,e", "bit 6,h", "bit 6,l", "bit 6,(hl)", "bit 6,a", "bit 7,b", "bit 7,c", "bit 7,d", "bit 7,e", "bit 7,h", "bit 7,l", "bit 7,(hl)", "bit 7,a", "res 0,b", "res 0,c", "res 0,d", "res 0,e", "res 0,h", "res 0,l", "res 0,(hl)", "res 0,a", "res 1,b", "res 1,c", "res 1,d", "res 1,e", "res 1,h", "res 1,l", "res 1,(hl)", "res 1,a", "res 2,b", "res 2,c", "res 2,d", "res 2,e", "res 2,h", "res 2,l", "res 2,(hl)", "res 2,a", "res 3,b", "res 3,c", "res 3,d", "res 3,e", "res 3,h", "res 3,l", "res 3,(hl)", "res 3,a", "res 4,b", "res 4,c", "res 4,d", "res 4,e", "res 4,h", "res 4,l", "res 4,(hl)", "res 4,a", "res 5,b", "res 5,c", "res 5,d", "res 5,e", "res 5,h", "res 5,l", "res 5,(hl)", "res 5,a", "res 6,b", "res 6,c", "res 6,d", "res 6,e", "res 6,h", "res 6,l", "res 6,(hl)", "res 6,a", "res 7,b", "res 7,c", "res 7,d", "res 7,e", "res 7,h", "res 7,l", "res 7,(hl)", "res 7,a", "set 0,b", "set 0,c", "set 0,d", "set 0,e", "set 0,h", "set 0,l", "set 0,(hl)", "set 0,a", "set 1,b", "set 1,c", "set 1,d", "set 1,e", "set 1,h", "set 1,l", "set 1,(hl)", "set 1,a", "set 2,b", "set 2,c", "set 2,d", "set 2,e", "set 2,h", "set 2,l", "set 2,(hl)", "set 2,a", "set 3,b", "set 3,c", "set 3,d", "set 3,e", "set 3,h", "set 3,l", "set 3,(hl)", "set 3,a", "set 4,b", "set 4,c", "set 4,d", "set 4,e", "set 4,h", "set 4,l", "set 4,(hl)", "set 4,a", "set 5,b", "set 5,c", "set 5,d", "set 5,e", "set 5,h", "set 5,l", "set 5,(hl)", "set 5,a", "set 6,b", "set 6,c", "set 6,d", "set 6,e", "set 6,h", "set 6,l", "set 6,(hl)", "set 6,a", "set 7,b", "set 7,c", "set 7,d", "set 7,e", "set 7,h", "set 7,l", "set 7,(hl)", "set 7,a"}; +// const char *ix_opcodes[256] = {"", "", "", "", "inc b", "dec b", "ld b,N", "", "", "add ix,bc", "", "", "inc c", "dec c", "ld c,N", "", "", "", "", "", "inc d", "dec d", "ld d,N", "", "", "add ix,de", "", "", "inc e", "dec e", "ld e,N", "", "", "ld ix,NN", "ld (NN),ix", "inc ix", "inc ixh", "dec ixh", "ld ixh,N", "", "", "add ix,ix", "ld ix,(NN)", "dec ix", "inc ixl", "dec ixl", "ld ixl,N", "", "", "", "", "", "inc (ix+D)", "dec (ix+D)", "ld (ix+D),N", "", "", "add ix,sp", "", "", "inc a", "dec a", "ld a,N", "", "ld b,b", "ld b,c", "ld b,d", "ld b,e", "ld b,ixh", "ld b,ixl", "ld b,(ix+D)", "ld b,a", "ld c,b", "ld c,c", "ld c,d", "ld c,e", "ld c,ixh", "ld c,ixl", "ld c,(ix+D)", "ld c,a", "ld d,b", "ld d,c", "ld d,d", "ld d,e", "ld d,ixh", "ld d,ixl", "ld d,(ix+D)", "ld d,a", "ld e,b", "ld e,c", "ld e,d", "ld e,e", "ld e,ixh", "ld e,ixl", "ld e,(ix+D)", "ld e,a", "ld ixh,b", "ld ixh,c", "ld ixh,d", "ld ixh,e", "ld ixh,ixh", "ld ixh,ixl", "ld h,(ix+D)", "ld ixh,a", "ld ixl,b", "ld ixl,c", "ld ixl,d", "ld ixl,e", "ld ixl,ixh", "ld ixl,ixl", "ld l,(ix+D)", "ld ixl,a", "ld (ix+D),b", "ld (ix+D),c", "ld (ix+D),d", "ld (ix+D),e", "ld (ix+D),h", "ld (ix+D),l", "", "ld (ix+D),a", "ld a,b", "ld a,c", "ld a,d", "ld a,e", "ld a,ixh", "ld a,ixl", "ld a,(ix+D)", "ld a,a", "add a,b", "add a,c", "add a,d", "add a,e", "add a,ixh", "add a,ixl", "add a,(ix+D)", "add a,a", "adc a,b", "adc a,c", "adc a,d", "adc a,e", "adc a,ixh", "adc a,ixl", "adc a,(ix+D)", "adc a,a", "sub b", "sub c", "sub d", "sub e", "sub ixh", "sub ixl", "sub (ix+D)", "sub a", "sbc a,b", "sbc a,c", "sbc a,d", "sbc a,e", "sbc a,ixh", "sbc a,ixl", "sbc a,(ix+D)", "sbc a,a", "and b", "and c", "and d", "and e", "and ixh", "and ixl", "and (ix+D)", "and a", "xor b", "xor c", "xor d", "xor e", "xor ixh", "xor ixl", "xor (ix+D)", "xor a", "or b", "or c", "or d", "or e", "or ixh", "or ixl", "or (ix+D)", "or a", "cp b", "cp c", "cp d", "cp e", "cp ixh", "cp ixl", "cp (ix+D)", "cp a", "", "", "", "", "", "", "", "", "", "", "", "_IX Bit_", "", "", "", "", "", "pop ix", "", "ex (sp),ix", "", "push ix", "", "", "", "jp (ix)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ld sp,ix", "", "", "", "", "", ""}; +// const char *ix_bit_opcodes[256] = {"rlc (ix+D),b", "rlc (ix+D),c", "rlc (ix+D),d", "rlc (ix+D),e", "rlc (ix+D),h", "rlc (ix+D),l", "rlc (ix+D)", "rlc (ix+D),a", "rrc (ix+D),b", "rrc (ix+D),c", "rrc (ix+D),d", "rrc (ix+D),e", "rrc (ix+D),h", "rrc (ix+D),l", "rrc (ix+D)", "rrc (ix+D),a", "rl (ix+D),b", "rl (ix+D),c", "rl (ix+D),d", "rl (ix+D),e", "rl (ix+D),h", "rl (ix+D),l", "rl (ix+D)", "rl (ix+D),a", "rr (ix+D),b", "rr (ix+D),c", "rr (ix+D),d", "rr (ix+D),e", "rr (ix+D),h", "rr (ix+D),l", "rr (ix+D)", "rr (ix+D),a", "sla (ix+D),b", "sla (ix+D),c", "sla (ix+D),d", "sla (ix+D),e", "sla (ix+D),h", "sla (ix+D),l", "sla (ix+D)", "sla (ix+D),a", "sra (ix+D),b", "sra (ix+D),c", "sra (ix+D),d", "sra (ix+D),e", "sra (ix+D),h", "sra (ix+D),l", "sra (ix+D)", "sra (ix+D),a", "sll (ix+D),b", "sll (ix+D),c", "sll (ix+D),d", "sll (ix+D),e", "sll (ix+D),h", "sll (ix+D),l", "sll (ix+D)", "sll (ix+D),a", "srl (ix+D),b", "srl (ix+D),c", "srl (ix+D),d", "srl (ix+D),e", "srl (ix+D),h", "srl (ix+D),l", "srl (ix+D)", "srl (ix+D),a", "bit 0,(ix+D)", "bit 0,(ix+D)", "bit 0,(ix+D)", "bit 0,(ix+D)", "bit 0,(ix+D)", "bit 0,(ix+D)", "bit 0,(ix+D)", "bit 0,(ix+D)", "bit 1,(ix+D)", "bit 1,(ix+D)", "bit 1,(ix+D)", "bit 1,(ix+D)", "bit 1,(ix+D)", "bit 1,(ix+D)", "bit 1,(ix+D)", "bit 1,(ix+D)", "bit 2,(ix+D)", "bit 2,(ix+D)", "bit 2,(ix+D)", "bit 2,(ix+D)", "bit 2,(ix+D)", "bit 2,(ix+D)", "bit 2,(ix+D)", "bit 2,(ix+D)", "bit 3,(ix+D)", "bit 3,(ix+D)", "bit 3,(ix+D)", "bit 3,(ix+D)", "bit 3,(ix+D)", "bit 3,(ix+D)", "bit 3,(ix+D)", "bit 3,(ix+D)", "bit 4,(ix+D)", "bit 4,(ix+D)", "bit 4,(ix+D)", "bit 4,(ix+D)", "bit 4,(ix+D)", "bit 4,(ix+D)", "bit 4,(ix+D)", "bit 4,(ix+D)", "bit 5,(ix+D)", "bit 5,(ix+D)", "bit 5,(ix+D)", "bit 5,(ix+D)", "bit 5,(ix+D)", "bit 5,(ix+D)", "bit 5,(ix+D)", "bit 5,(ix+D)", "bit 6,(ix+D)", "bit 6,(ix+D)", "bit 6,(ix+D)", "bit 6,(ix+D)", "bit 6,(ix+D)", "bit 6,(ix+D)", "bit 6,(ix+D)", "bit 6,(ix+D)", "bit 7,(ix+D)", "bit 7,(ix+D)", "bit 7,(ix+D)", "bit 7,(ix+D)", "bit 7,(ix+D)", "bit 7,(ix+D)", "bit 7,(ix+D)", "bit 7,(ix+D)", "res 0,(ix+D),b", "res 0,(ix+D),c", "res 0,(ix+D),d", "res 0,(ix+D),e", "res 0,(ix+D),h", "res 0,(ix+D),l", "res 0,(ix+D)", "res 0,(ix+D),a", "res 1,(ix+D),b", "res 1,(ix+D),c", "res 1,(ix+D),d", "res 1,(ix+D),e", "res 1,(ix+D),h", "res 1,(ix+D),l", "res 1,(ix+D)", "res 1,(ix+D),a", "res 2,(ix+D),b", "res 2,(ix+D),c", "res 2,(ix+D),d", "res 2,(ix+D),e", "res 2,(ix+D),h", "res 2,(ix+D),l", "res 2,(ix+D)", "res 2,(ix+D),a", "res 3,(ix+D),b", "res 3,(ix+D),c", "res 3,(ix+D),d", "res 3,(ix+D),e", "res 3,(ix+D),h", "res 3,(ix+D),l", "res 3,(ix+D)", "res 3,(ix+D),a", "res 4,(ix+D),b", "res 4,(ix+D),c", "res 4,(ix+D),d", "res 4,(ix+D),e", "res 4,(ix+D),h", "res 4,(ix+D),l", "res 4,(ix+D)", "res 4,(ix+D),a", "res 5,(ix+D),b", "res 5,(ix+D),c", "res 5,(ix+D),d", "res 5,(ix+D),e", "res 5,(ix+D),h", "res 5,(ix+D),l", "res 5,(ix+D)", "res 5,(ix+D),a", "res 6,(ix+D),b", "res 6,(ix+D),c", "res 6,(ix+D),d", "res 6,(ix+D),e", "res 6,(ix+D),h", "res 6,(ix+D),l", "res 6,(ix+D)", "res 6,(ix+D),a", "res 7,(ix+D),b", "res 7,(ix+D),c", "res 7,(ix+D),d", "res 7,(ix+D),e", "res 7,(ix+D),h", "res 7,(ix+D),l", "res 7,(ix+D)", "res 7,(ix+D),a", "set 0,(ix+D),b", "set 0,(ix+D),c", "set 0,(ix+D),d", "set 0,(ix+D),e", "set 0,(ix+D),h", "set 0,(ix+D),l", "set 0,(ix+D)", "set 0,(ix+D),a", "set 1,(ix+D),b", "set 1,(ix+D),c", "set 1,(ix+D),d", "set 1,(ix+D),e", "set 1,(ix+D),h", "set 1,(ix+D),l", "set 1,(ix+D)", "set 1,(ix+D),a", "set 2,(ix+D),b", "set 2,(ix+D),c", "set 2,(ix+D),d", "set 2,(ix+D),e", "set 2,(ix+D),h", "set 2,(ix+D),l", "set 2,(ix+D)", "set 2,(ix+D),a", "set 3,(ix+D),b", "set 3,(ix+D),c", "set 3,(ix+D),d", "set 3,(ix+D),e", "set 3,(ix+D),h", "set 3,(ix+D),l", "set 3,(ix+D)", "set 3,(ix+D),a", "set 4,(ix+D),b", "set 4,(ix+D),c", "set 4,(ix+D),d", "set 4,(ix+D),e", "set 4,(ix+D),h", "set 4,(ix+D),l", "set 4,(ix+D)", "set 4,(ix+D),a", "set 5,(ix+D),b", "set 5,(ix+D),c", "set 5,(ix+D),d", "set 5,(ix+D),e", "set 5,(ix+D),h", "set 5,(ix+D),l", "set 5,(ix+D)", "set 5,(ix+D),a", "set 6,(ix+D),b", "set 6,(ix+D),c", "set 6,(ix+D),d", "set 6,(ix+D),e", "set 6,(ix+D),h", "set 6,(ix+D),l", "set 6,(ix+D)", "set 6,(ix+D),a", "set 7,(ix+D),b", "set 7,(ix+D),c", "set 7,(ix+D),d", "set 7,(ix+D),e", "set 7,(ix+D),h", "set 7,(ix+D),l", "set 7,(ix+D)", "set 7,(ix+D),a"}; +// const char *misc_opcodes[128] = {"in b,(c)", "out (c),b", "sbc hl,bc", "ld (NN),bc", "neg", "retn", "im 0", "ld i,a", "in c,(c)", "out (c),c", "adc hl,bc", "ld bc,(NN)", "mlt bc", "reti", "", "ld r,a", "in d,(c)", "out (c),d", "sbc hl,de", "ld (NN),de", "", "", "im 1", "ld a,i", "in e,(c)", "out (c),e", "adc hl,de", "ld de,(NN)", "mlt de", "", "im 2", "ld a,r", "in h,(c)", "out (c),h", "sbc hl,hl", "ld (NN),hl", "tst N", "", "", "rrd", "in l,(c)", "out (c),l", "adc hl,hl", "ld hl,(NN)", "mlt hl", "", "", "rld", "in (c)", "out (c),0", "sbc hl,sp", "ld (NN),sp", "tstio N", "", "slp", "", "in a,(c)", "out (c),a", "adc hl,sp", "ld sp,(NN)", "mlt sp", "", "", "", "", "", "", "otim", "", "", "", "", "", "", "", "otdm", "", "", "", "", "", "", "", "otimr", "", "", "", "", "", "", "", "otdmr", "", "", "", "", "ldi", "cpi", "ini", "outi", "", "", "", "", "ldd", "cpd", "ind", "outd", "", "", "", "", "ldir", "cpir", "inir", "otir", "", "", "", "", "lddr", "cpdr", "indr", "otdr", "", "", "", ""}; +// const char *iy_opcodes[256] = {"", "", "", "", "inc b", "dec b", "ld b,N", "", "", "add iy,bc", "", "", "inc c", "dec c", "ld c,N", "", "", "", "", "", "inc d", "dec d", "ld d,N", "", "", "add iy,de", "", "", "inc e", "dec e", "ld e,N", "", "", "ld iy,NN", "ld (NN),iy", "inc iy", "inc iyh", "dec iyh", "ld iyh,N", "", "", "add iy,iy", "ld iy,(NN)", "dec iy", "inc iyl", "dec iyl", "ld iyl,N", "", "", "", "", "", "inc (iy+D)", "dec (iy+D)", "ld (iy+D),N", "", "", "add iy,sp", "", "", "inc a", "dec a", "ld a,N", "", "ld b,b", "ld b,c", "ld b,d", "ld b,e", "ld b,iyh", "ld b,iyl", "ld b,(iy+D)", "ld b,a", "ld c,b", "ld c,c", "ld c,d", "ld c,e", "ld c,iyh", "ld c,iyl", "ld c,(iy+D)", "ld c,a", "ld d,b", "ld d,c", "ld d,d", "ld d,e", "ld d,iyh", "ld d,iyl", "ld d,(iy+D)", "ld d,a", "ld e,b", "ld e,c", "ld e,d", "ld e,e", "ld e,iyh", "ld e,iyl", "ld e,(iy+D)", "ld e,a", "ld iyh,b", "ld iyh,c", "ld iyh,d", "ld iyh,e", "ld iyh,iyh", "ld iyh,iyl", "ld h,(iy+D)", "ld iyh,a", "ld iyl,b", "ld iyl,c", "ld iyl,d", "ld iyl,e", "ld iyl,iyh", "ld iyl,iyl", "ld l,(iy+D)", "ld iyl,a", "ld (iy+D),b", "ld (iy+D),c", "ld (iy+D),d", "ld (iy+D),e", "ld (iy+D),h", "ld (iy+D),l", "", "ld (iy+D),a", "ld a,b", "ld a,c", "ld a,d", "ld a,e", "ld a,iyh", "ld a,iyl", "ld a,(iy+D)", "ld a,a", "add a,b", "add a,c", "add a,d", "add a,e", "add a,iyh", "add a,iyl", "add a,(iy+D)", "add a,a", "adc a,b", "adc a,c", "adc a,d", "adc a,e", "adc a,iyh", "adc a,iyl", "adc a,(iy+D)", "adc a,a", "sub b", "sub c", "sub d", "sub e", "sub iyh", "sub iyl", "sub (iy+D)", "sub a", "sbc a,b", "sbc a,c", "sbc a,d", "sbc a,e", "sbc a,iyh", "sbc a,iyl", "sbc a,(iy+D)", "sbc a,a", "and b", "and c", "and d", "and e", "and iyh", "and iyl", "and (iy+D)", "and a", "xor b", "xor c", "xor d", "xor e", "xor iyh", "xor iyl", "xor (iy+D)", "xor a", "or b", "or c", "or d", "or e", "or iyh", "or iyl", "or (iy+D)", "or a", "cp b", "cp c", "cp d", "cp e", "cp iyh", "cp iyl", "cp (iy+D)", "cp a", "", "", "", "", "", "", "", "", "", "", "", "_IY Bit_", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "pop iy", "", "ex (sp),iy", "", "push iy", "", "", "", "jp (iy)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ld sp,iy", "", "", "", "", "", ""}; +// const char *iy_bit_opcodes[256] = {"rlc (iy+D),b", "rlc (iy+D),c", "rlc (iy+D),d", "rlc (iy+D),e", "rlc (iy+D),h", "rlc (iy+D),l", "rlc (iy+D)", "rlc (iy+D),a", "rrc (iy+D),b", "rrc (iy+D),c", "rrc (iy+D),d", "rrc (iy+D),e", "rrc (iy+D),h", "rrc (iy+D),l", "rrc (iy+D)", "rrc (iy+D),a", "rl (iy+D),b", "rl (iy+D),c", "rl (iy+D),d", "rl (iy+D),e", "rl (iy+D),h", "rl (iy+D),l", "rl (iy+D)", "rl (iy+D),a", "rr (iy+D),b", "rr (iy+D),c", "rr (iy+D),d", "rr (iy+D),e", "rr (iy+D),h", "rr (iy+D),l", "rr (iy+D)", "rr (iy+D),a", "sla (iy+D),b", "sla (iy+D),c", "sla (iy+D),d", "sla (iy+D),e", "sla (iy+D),h", "sla (iy+D),l", "sla (iy+D)", "sla (iy+D),a", "sra (iy+D),b", "sra (iy+D),c", "sra (iy+D),d", "sra (iy+D),e", "sra (iy+D),h", "sra (iy+D),l", "sra (iy+D)", "sra (iy+D),a", "sll (iy+D),b", "sll (iy+D),c", "sll (iy+D),d", "sll (iy+D),e", "sll (iy+D),h", "sll (iy+D),l", "sll (iy+D)", "sll (iy+D),a", "srl (iy+D),b", "srl (iy+D),c", "srl (iy+D),d", "srl (iy+D),e", "srl (iy+D),h", "srl (iy+D),l", "srl (iy+D)", "srl (iy+D),a", "bit 0,(iy+D)", "bit 0,(iy+D)", "bit 0,(iy+D)", "bit 0,(iy+D)", "bit 0,(iy+D)", "bit 0,(iy+D)", "bit 0,(iy+D)", "bit 0,(iy+D)", "bit 1,(iy+D)", "bit 1,(iy+D)", "bit 1,(iy+D)", "bit 1,(iy+D)", "bit 1,(iy+D)", "bit 1,(iy+D)", "bit 1,(iy+D)", "bit 1,(iy+D)", "bit 2,(iy+D)", "bit 2,(iy+D)", "bit 2,(iy+D)", "bit 2,(iy+D)", "bit 2,(iy+D)", "bit 2,(iy+D)", "bit 2,(iy+D)", "bit 2,(iy+D)", "bit 3,(iy+D)", "bit 3,(iy+D)", "bit 3,(iy+D)", "bit 3,(iy+D)", "bit 3,(iy+D)", "bit 3,(iy+D)", "bit 3,(iy+D)", "bit 3,(iy+D)", "bit 4,(iy+D)", "bit 4,(iy+D)", "bit 4,(iy+D)", "bit 4,(iy+D)", "bit 4,(iy+D)", "bit 4,(iy+D)", "bit 4,(iy+D)", "bit 4,(iy+D)", "bit 5,(iy+D)", "bit 5,(iy+D)", "bit 5,(iy+D)", "bit 5,(iy+D)", "bit 5,(iy+D)", "bit 5,(iy+D)", "bit 5,(iy+D)", "bit 5,(iy+D)", "bit 6,(iy+D)", "bit 6,(iy+D)", "bit 6,(iy+D)", "bit 6,(iy+D)", "bit 6,(iy+D)", "bit 6,(iy+D)", "bit 6,(iy+D)", "bit 6,(iy+D)", "bit 7,(iy+D)", "bit 7,(iy+D)", "bit 7,(iy+D)", "bit 7,(iy+D)", "bit 7,(iy+D)", "bit 7,(iy+D)", "bit 7,(iy+D)", "bit 7,(iy+D)", "res 0,(iy+D),b", "res 0,(iy+D),c", "res 0,(iy+D),d", "res 0,(iy+D),e", "res 0,(iy+D),h", "res 0,(iy+D),l", "res 0,(iy+D)", "res 0,(iy+D),a", "res 1,(iy+D),b", "res 1,(iy+D),c", "res 1,(iy+D),d", "res 1,(iy+D),e", "res 1,(iy+D),h", "res 1,(iy+D),l", "res 1,(iy+D)", "res 1,(iy+D),a", "res 2,(iy+D),b", "res 2,(iy+D),c", "res 2,(iy+D),d", "res 2,(iy+D),e", "res 2,(iy+D),h", "res 2,(iy+D),l", "res 2,(iy+D)", "res 2,(iy+D),a", "res 3,(iy+D),b", "res 3,(iy+D),c", "res 3,(iy+D),d", "res 3,(iy+D),e", "res 3,(iy+D),h", "res 3,(iy+D),l", "res 3,(iy+D)", "res 3,(iy+D),a", "res 4,(iy+D),b", "res 4,(iy+D),c", "res 4,(iy+D),d", "res 4,(iy+D),e", "res 4,(iy+D),h", "res 4,(iy+D),l", "res 4,(iy+D)", "res 4,(iy+D),a", "res 5,(iy+D),b", "res 5,(iy+D),c", "res 5,(iy+D),d", "res 5,(iy+D),e", "res 5,(iy+D),h", "res 5,(iy+D),l", "res 5,(iy+D)", "res 5,(iy+D),a", "res 6,(iy+D),b", "res 6,(iy+D),c", "res 6,(iy+D),d", "res 6,(iy+D),e", "res 6,(iy+D),h", "res 6,(iy+D),l", "res 6,(iy+D)", "res 6,(iy+D),a", "res 7,(iy+D),b", "res 7,(iy+D),c", "res 7,(iy+D),d", "res 7,(iy+D),e", "res 7,(iy+D),h", "res 7,(iy+D),l", "res 7,(iy+D)", "res 7,(iy+D),a", "set 0,(iy+D),b", "set 0,(iy+D),c", "set 0,(iy+D),d", "set 0,(iy+D),e", "set 0,(iy+D),h", "set 0,(iy+D),l", "set 0,(iy+D)", "set 0,(iy+D),a", "set 1,(iy+D),b", "set 1,(iy+D),c", "set 1,(iy+D),d", "set 1,(iy+D),e", "set 1,(iy+D),h", "set 1,(iy+D),l", "set 1,(iy+D)", "set 1,(iy+D),a", "set 2,(iy+D),b", "set 2,(iy+D),c", "set 2,(iy+D),d", "set 2,(iy+D),e", "set 2,(iy+D),h", "set 2,(iy+D),l", "set 2,(iy+D)", "set 2,(iy+D),a", "set 3,(iy+D),b", "set 3,(iy+D),c", "set 3,(iy+D),d", "set 3,(iy+D),e", "set 3,(iy+D),h", "set 3,(iy+D),l", "set 3,(iy+D)", "set 3,(iy+D),a", "set 4,(iy+D),b", "set 4,(iy+D),c", "set 4,(iy+D),d", "set 4,(iy+D),e", "set 4,(iy+D),h", "set 4,(iy+D),l", "set 4,(iy+D)", "set 4,(iy+D),a", "set 5,(iy+D),b", "set 5,(iy+D),c", "set 5,(iy+D),d", "set 5,(iy+D),e", "set 5,(iy+D),h", "set 5,(iy+D),l", "set 5,(iy+D)", "set 5,(iy+D),a", "set 6,(iy+D),b", "set 6,(iy+D),c", "set 6,(iy+D),d", "set 6,(iy+D),e", "set 6,(iy+D),h", "set 6,(iy+D),l", "set 6,(iy+D)", "set 6,(iy+D),a", "set 7,(iy+D),b", "set 7,(iy+D),c", "set 7,(iy+D),d", "set 7,(iy+D),e", "set 7,(iy+D),h", "set 7,(iy+D),l", "set 7,(iy+D)", "set 7,(iy+D),a"}; + + void loadSymbols() + { + used_symbols.clear(); + for (int i=0; i<65536; ++i) symbols[i][0] = 0; + FILE *f = fopen("symbols.txt", "r"); + while (true) { + uint16_t address; + char tmp[15]; + const int result = fscanf(f, "%x %s", &address, tmp); + if (result != 2) break; + strcpy(symbols[address], tmp); + used_symbols.push_back(address); + } + fclose(f); + } + + void saveSymbols() + { + FILE *f = fopen("symbols.txt", "w"); + for (auto sym_addr : used_symbols) + { + fprintf(f, "0x%x %s\n", sym_addr, symbols[sym_addr]); + } + fclose(f); + } + + const char *getBase(const uint16_t pos) + { + if (mem::read(pos) == 0xCB) { + opcode_size=2; + return cb_opcodes[mem::read(pos+1)]; + } else if (mem::read(pos) == 0xDD) { + if (mem::read(pos+1) == 0xCB) { + opcode_size=4; + return ix_bit_opcodes[mem::read(pos+3)]; + } else { + opcode_size=2; + return ix_opcodes[mem::read(pos+1)]; + } + } else if (mem::read(pos) == 0xED) { + opcode_size=2; + return misc_opcodes[(mem::read(pos+1))-64]; + } else if (mem::read(pos) == 0xFD) { + if (mem::read(pos+1) == 0xCB) { + opcode_size=4; + return iy_bit_opcodes[mem::read(pos+3)]; + } else { + opcode_size=2; + return iy_opcodes[mem::read(pos+1)]; + } + } else { + opcode_size=1; + return base_opcodes[mem::read(pos)]; + } + } + + void printOpcode(const uint16_t pos) + { + char hex[4]; + for (int i=0; i<4;++i) + { + if (opcode_size>i) + sprintf(hex, "%02x ", mem::read(pos+i)); + else + sprintf(hex, " "); + strcat(buffer, hex); + } + } + + const char *getAsm(const uint16_t pos) + { + opcode_size = 0; + char base[256]; + strcpy(buffer, getBase(pos)); + + if (strstr(buffer, "4x")) + { + opcode_size+=2; + const uint8_t memvalue = mem::read(pos); + const uint16_t address = pos + ((memvalue==0xFD) || (memvalue==0xDD) || (memvalue==0xED)?2:1); + const uint16_t word = mem::read(address) + (mem::read(address+1)<<8); + if (symbols[word][0]!=0) { + char *p = strstr(buffer, "$"); + (*p)='%'; p++; + (*p)='s'; p++; + while (*(p-1) != 0) { + *p = *(p+3); + p++; + } + strcpy(base, buffer); + sprintf(buffer, base, symbols[word]); + } else { + strcpy(base, buffer); + sprintf(buffer, base, word); + } + } + + if (strstr(buffer, "2x") && strstr(buffer, "hhd")) + { + opcode_size = 4; + strcpy(base, buffer); + sprintf(buffer, base, mem::read(pos+2), (int8_t)mem::read(pos+3)); + return buffer; + } + + if (strstr(buffer, "2x")) + { + opcode_size+=1; + strcpy(base, buffer); + sprintf(buffer, base, mem::read(pos+1)); + } + + if (strstr(buffer, "Xx")) + { + strcpy(base, buffer); + *strstr(base, "Xx") = '4'; + opcode_size+=1; + + if (opcode_size>4) { + opcode_size=4; + sprintf(buffer, base, pos + opcode_size + (int8_t)mem::read(pos+2)); + } else { + sprintf(buffer, base, pos + opcode_size + (int8_t)mem::read(pos+1)); + } + } + + if (strstr(buffer, "hhd")) { + opcode_size+=1; + + strcpy(base, buffer); + if (opcode_size>4) { + opcode_size=4; + sprintf(buffer, base, (int8_t)mem::read(pos+3)); + } else { + sprintf(buffer, base, (int8_t)mem::read(pos+2)); + } + } + + return buffer; + } + + const char *getOpcode(const uint16_t pos) + { + opcode_size = 0; + buffer[0]=0; + const char *base = getBase(pos); + + if (strstr(base, "4x")) opcode_size+=2; + if (strstr(base, "2x")) opcode_size+=1; + if (strstr(base, "Xx")) opcode_size+=1; + if (strstr(base, "hh")) opcode_size+=1; + if (opcode_size>4) opcode_size=4; + printOpcode(pos); + return buffer; + } + + const int getOpcodeSize(const uint16_t pos) + { + opcode_size = 0; + const char *base = getBase(pos); + + if (strstr(base, "4x")) opcode_size+=2; + if (strstr(base, "2x")) opcode_size+=1; + if (strstr(base, "Xx")) opcode_size+=1; + if (strstr(base, "hh")) opcode_size+=1; + if (opcode_size>4) opcode_size=4; + return opcode_size; + } + + const char *getSymbol(const uint16_t pos) + { + return symbols[pos]; + } + + void setSymbol(const uint16_t pos, const char *sym) + { + if (sym) { + strcpy(symbols[pos], sym); + } else { + symbols[pos][0] = 0; + } + used_symbols.clear(); + for (int i=0; i<65536; ++i) if (symbols[i][0]!=0) used_symbols.push_back(i); + saveSymbols(); + } + + const int getNumSymbols() + { + return used_symbols.size(); + } + + const uint16_t getSymbolAddress(const int pos) + { + return used_symbols[pos]; + } + + +} diff --git a/z80dis.h b/z80dis.h new file mode 100644 index 0000000..6fc81d3 --- /dev/null +++ b/z80dis.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace z80dis +{ + void loadSymbols(); + void saveSymbols(); + const char *getAsm(const uint16_t pos); + const char *getOpcode(const uint16_t pos); + const int getOpcodeSize(const uint16_t pos); + const char *getSymbol(const uint16_t pos); + void setSymbol(const uint16_t pos, const char *sym); + + const int getNumSymbols(); + const uint16_t getSymbolAddress(const int pos); +}