diff --git a/main.cpp b/main.cpp index 6aa65c3..b665c65 100644 --- a/main.cpp +++ b/main.cpp @@ -15,6 +15,9 @@ #include "z80mem.h" #include "zx_48mem.h" #include "zx_128mem.h" +#include "z80viewer.h" +#include "zx_128bankviewer.h" +#include "zx_128pageviewer.h" uint8_t memory[65536]; uint32_t time = 0; @@ -87,8 +90,16 @@ int main(int argc, char *argv[]) SDL_Init(SDL_INIT_EVERYTHING); z80debug::init(); - zxscreen::init(SCREEN_MODE_128K); - //zxscreen::init(SCREEN_MODE_48K); + zxscreen::init(SCREEN_MODE_48K); + //zxscreen::init(SCREEN_MODE_128K); + + //z80viewer *v = new zx_128bankviewer(); + //v->show(); + //z80viewer::registerViewer("128BANK", v); + + //v = new zx_128pageviewer(); + //v->show(); + //z80viewer::registerViewer("128PAGE", v); ui::menu::init(); ui::menu::setexitcallback(actions::exitMenu); @@ -121,6 +132,7 @@ int main(int argc, char *argv[]) if (argc==3) { z80debug::loadngo(argv[1], argv[2]); } z80debug::stop(); + z80debug::stop(); bool should_exit = false; SDL_Event e; @@ -156,6 +168,7 @@ int main(int argc, char *argv[]) } else { z80debug::show(); } + z80viewer::refreshAll(); } else if (e.key.keysym.scancode==SDL_SCANCODE_F10) { if (z80debug::debugging()) { z80debug::show(); @@ -165,6 +178,7 @@ int main(int argc, char *argv[]) zxscreen::fullrefresh(); zxscreen::redraw(); z80analyze::refresh(); + z80viewer::refreshAll(); } } else if (e.key.keysym.scancode==SDL_SCANCODE_F11) { if (z80debug::debugging()) { @@ -175,6 +189,7 @@ int main(int argc, char *argv[]) zxscreen::refresh(dt); zxscreen::redraw(); z80analyze::refresh(); + z80viewer::refreshAll(); } } else if (e.key.keysym.scancode==SDL_SCANCODE_F12) { if (z80debug::debugging()) { @@ -185,6 +200,7 @@ int main(int argc, char *argv[]) zxscreen::refresh(dt); zxscreen::redraw(); z80analyze::refresh(); + z80viewer::refreshAll(); } } result = ui::window::sendEvent(e.key.windowID, &e); @@ -243,6 +259,7 @@ int main(int argc, char *argv[]) t_states -= update_freq; time = SDL_GetTicks(); z80analyze::refresh(); + z80viewer::refreshAll(); } z80analyze::refresh(true); diff --git a/z80.cpp b/z80.cpp index beb5520..fcd46a2 100644 --- a/z80.cpp +++ b/z80.cpp @@ -1,7 +1,7 @@ #include "z80.h" #include "z80debug.h" #include "z80mem.h" -#include "zx_tape.h" +//#include "zx_tape.h" #include namespace z80 @@ -15,8 +15,8 @@ namespace z80 bool options[Z80_NUM_OPTIONS] = { true, false }; int calls_stacked = 0; - int (*in_ports[65536])(int); - void (*out_ports[65536])(int, int); + int (*in_ports[256])(int); + void (*out_ports[256])(int, int); //#define _rM16(a) (uint16_t*)&memory[a] //#define rM16(a) *_rM16(a) @@ -186,10 +186,10 @@ namespace z80 { t+=1; reading_m1 = true; - if (rPC==0x056c) { + /*if (rPC==0x056c) { zx_tape::rewind(); zx_tape::play(); - } + }*/ return READ_MEM_8(); } @@ -1008,6 +1008,7 @@ namespace z80 t+=4; if (port == 0x10000) { port = rBC; + if (rC==0xfe) port = 0xfe; } if (out_ports[port&0xff]) out_ports[port&0xff](port, val); } @@ -2265,7 +2266,7 @@ namespace z80 switch (opcode) { case 0x40: rB = IN(); break; - case 0x41: OUT(rB, rC); break; + case 0x41: OUT(rB); break; case 0x42: SBC16(_rHL, rBC); break; case 0x43: WRITE_MEM_16(READ_MEM_16(), rBC);break; case 0x44: NEG(); break; @@ -2273,42 +2274,42 @@ namespace z80 case 0x46: IM(0); break; case 0x47: rI = rA; t++; break; case 0x48: rC = IN(); break; - case 0x49: OUT(rC, rC); break; + case 0x49: OUT(rC); break; case 0x4A: ADC16(_rHL, rBC); break; case 0x4B: rBC = READ_MEM_16(READ_MEM_16());break; case 0x4D: RETI(); break; case 0x4F: rR = rA; t++; break; case 0x50: rD = IN(); break; - case 0x51: OUT(rD, rC); break; + case 0x51: OUT(rD); break; case 0x52: SBC16(_rHL, rDE); break; case 0x53: WRITE_MEM_16(READ_MEM_16(), rDE);break; case 0x56: IM(1); break; case 0x57: LD_A_I(); break; case 0x58: rE = IN(); break; - case 0x59: OUT(rE, rC); break; + case 0x59: OUT(rE); break; case 0x5A: ADC16(_rHL, rDE); break; case 0x5B: rDE = READ_MEM_16(READ_MEM_16());break; case 0x5E: IM(2); break; case 0x5F: LD_A_R(); break; case 0x60: rH = IN(); break; - case 0x61: OUT(rH, rC); break; + case 0x61: OUT(rH); break; case 0x62: SBC16(_rHL, rHL); break; case 0x63: WRITE_MEM_16(READ_MEM_16(), rHL);break; case 0x67: RRD(); break; case 0x68: rL = IN(); break; - case 0x69: OUT(rL, rC); break; + case 0x69: OUT(rL); break; case 0x6A: ADC16(_rHL, rHL); break; case 0x6B: rHL = READ_MEM_16(READ_MEM_16());break; case 0x6F: RLD(); break; case 0x70: IN(); break; - case 0x71: OUT(0, rC); break; + case 0x71: OUT(0); break; case 0x72: SBC16(_rHL, rSP); break; case 0x73: WRITE_MEM_16(READ_MEM_16(), rSP);break; case 0x78: rA = IN(); break; - case 0x79: OUT(rA, rC); break; + case 0x79: OUT(rA); break; case 0x7A: ADC16(_rHL, rSP); break; case 0x7B: rSP = READ_MEM_16(READ_MEM_16());break; diff --git a/z80analyze.cpp b/z80analyze.cpp index 3a2994a..5ee39ce 100644 --- a/z80analyze.cpp +++ b/z80analyze.cpp @@ -84,6 +84,7 @@ namespace z80analyze SDL_SetWindowTitle(win, SDL_itoa(address, tmp, 16)); } } + void refresh(const bool conditional) { if (!win) return; diff --git a/z80debug.cpp b/z80debug.cpp index bef20da..85f6cc2 100644 --- a/z80debug.cpp +++ b/z80debug.cpp @@ -801,6 +801,7 @@ namespace z80debug } else if (strcmp(cmd, "r")==0 || strcmp(cmd, "reset")==0) { z80::reset(); z80::connect_port(0xfe, zx_ula::port_in, zx_ula::port_out); + history::reset(); z80debug::refresh(); z80analyze::refresh(); } else if (strcmp(cmd, "b")==0 || strcmp(cmd, "break")==0) { @@ -897,6 +898,7 @@ namespace z80debug 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(); @@ -1149,6 +1151,12 @@ namespace z80debug namespace history { + void reset() + { + buffer[0]=buffer[1]=0; + cursor=pos=top=0; + } + void store() { buffer[++top] = z80::getPC(); diff --git a/z80debug.h b/z80debug.h index d89d13b..a4c86b1 100644 --- a/z80debug.h +++ b/z80debug.h @@ -44,6 +44,7 @@ namespace z80debug void search(const char *seq=nullptr); namespace history { + void reset(); void store(); void gototop(); void goforward(); diff --git a/z80mem.h b/z80mem.h index b41a19e..aeacdea 100644 --- a/z80mem.h +++ b/z80mem.h @@ -36,6 +36,7 @@ class z80mem virtual uint32_t getSize() = 0; virtual uint8_t *rawPtr(uint32_t address) = 0; + virtual uint8_t *rawTagPtr(uint32_t address) = 0; protected: diff --git a/z80viewer.cpp b/z80viewer.cpp new file mode 100644 index 0000000..31368b6 --- /dev/null +++ b/z80viewer.cpp @@ -0,0 +1,33 @@ +#include "z80viewer.h" +#include "ui.h" +#include "ui_window.h" + +std::vector z80viewer::viewers; + +void z80viewer::registerViewer(const char *name, z80viewer *viewer) +{ + viewer_t v; + strcpy(v.name, name); + v.viewer = viewer; + viewers.push_back( v ); +} + +z80viewer *z80viewer::getViewer(const char *name) +{ + for (auto v : viewers) + { + if (strcmp(name, v.name)==0) return v.viewer; + } + return nullptr; +} + +void z80viewer::refreshAll() +{ + for (auto v : viewers) v.viewer->refresh(); +} + +bool z80viewer::handleEvents(SDL_Event *e) +{ + for (auto v : viewers) v.viewer->handleEvent(e); + return true; +} \ No newline at end of file diff --git a/z80viewer.h b/z80viewer.h new file mode 100644 index 0000000..f73e572 --- /dev/null +++ b/z80viewer.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include + +class z80viewer; + +struct viewer_t +{ + char name[12]; + z80viewer *viewer; +}; + +class z80viewer +{ + public: + virtual void show() = 0; + virtual void refresh() = 0; + virtual void hide() = 0; + virtual void focus() = 0; + virtual bool handleEvent(SDL_Event *e) = 0; + + static void registerViewer(const char *name, z80viewer *viewer); + static z80viewer *getViewer(const char *name); + static void refreshAll(); + static bool handleEvents(SDL_Event *e); + + protected: + SDL_Window *win = nullptr; + SDL_Renderer *ren = nullptr; + SDL_Texture *tex = nullptr; + SDL_Texture *uitex = nullptr; + + static std::vector viewers; +}; diff --git a/zx_128bankviewer.cpp b/zx_128bankviewer.cpp new file mode 100644 index 0000000..ab5dae6 --- /dev/null +++ b/zx_128bankviewer.cpp @@ -0,0 +1,60 @@ +#include "zx_128bankviewer.h" +#include "z80.h" +#include "z80mem.h" + +void zx_128bankviewer::show() +{ + if (!win) + { + win = SDL_CreateWindow("Z80 Analyzer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 128, 512, SDL_WINDOW_SHOWN); + ren = SDL_CreateRenderer(win, -1, 0); + tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 128, 512); + + //ui::window::registerWindow(SDL_GetWindowID(win), handleEvent); + } + refresh(); +} + + +void zx_128bankviewer::refresh() +{ + if (!win) return; + + Uint32 *pixels; + int pitch; + SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch); + for (int i=0; i<65536; ++i) + { + //uint8_t tag = z80::getMemTag(i); + //pixels[i] = tag==MEMTAG_NONE ? 0x808080 : tag==MEMTAG_DATA ? 0x0000FF : tag==MEMTAG_MIXED ? 0xFF00FF : 0x00FF00; + uint32_t none_color = i<0x4000 ? 0x101010 : i<0x5800 ? 0x202020 : i<0x5b00 ? 0x404040 : 0x808080; + uint8_t tag = z80mem::get()->getTag(i); + pixels[i] = !(tag & MEMTAG_TOUCHED) ? none_color : (tag & MEMTAG_TINST) ? 0x00FF00 : (tag & MEMTAG_TREPEAT) ? 0xFF0000 : 0x0000FF; + } + pixels[z80::getPC()] = 0xFFFFFF; + + SDL_UnlockTexture(tex); + SDL_RenderCopy(ren, tex, NULL, NULL); + SDL_RenderPresent(ren); +} + +void zx_128bankviewer::hide() +{ + //ui::window::unregisterWindow(SDL_GetWindowID(win)); + SDL_DestroyTexture(tex); tex = nullptr; + SDL_DestroyRenderer(ren); ren = nullptr; + SDL_DestroyWindow(win); win = nullptr; +} + +void zx_128bankviewer::focus() +{ + if (win) { + SDL_RaiseWindow(win); + refresh(); + } +} + +bool zx_128bankviewer::handleEvent(SDL_Event *e) +{ + return true; +} diff --git a/zx_128bankviewer.h b/zx_128bankviewer.h new file mode 100644 index 0000000..7641246 --- /dev/null +++ b/zx_128bankviewer.h @@ -0,0 +1,12 @@ +#pragma once +#include "z80viewer.h" + +class zx_128bankviewer : public z80viewer +{ + public: + void show(); + void refresh(); + void hide(); + void focus(); + bool handleEvent(SDL_Event *e); +}; diff --git a/zx_128mem.cpp b/zx_128mem.cpp index 561b5e0..75571de 100644 --- a/zx_128mem.cpp +++ b/zx_128mem.cpp @@ -6,7 +6,7 @@ #include #define ZX_128MEM_PAGE 0x07 -#define ZX_128MEM_SCREEN 0x04 +#define ZX_128MEM_SCREEN 0x08 #define ZX_128MEM_ROM 0x10 #define ZX_128MEM_DISPAG 0x20 @@ -157,4 +157,9 @@ uint32_t zx_128mem::getSize() uint8_t *zx_128mem::rawPtr(uint32_t address) { return &memory[address]; -} \ No newline at end of file +} + +uint8_t *zx_128mem::rawTagPtr(uint32_t address) +{ + return &tags[address]; +} diff --git a/zx_128mem.h b/zx_128mem.h index 5b3b756..af467ac 100644 --- a/zx_128mem.h +++ b/zx_128mem.h @@ -26,6 +26,7 @@ class zx_128mem : public z80mem uint32_t getSize(); uint8_t *rawPtr(uint32_t address); + uint8_t *rawTagPtr(uint32_t address); protected: diff --git a/zx_128pageviewer.cpp b/zx_128pageviewer.cpp new file mode 100644 index 0000000..910079e --- /dev/null +++ b/zx_128pageviewer.cpp @@ -0,0 +1,61 @@ +#include "zx_128pageviewer.h" +#include "z80.h" +#include "z80mem.h" + +void zx_128pageviewer::show() +{ + if (!win) + { + win = SDL_CreateWindow("ZX128 Page Viewer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1024, 128, SDL_WINDOW_SHOWN); + ren = SDL_CreateRenderer(win, -1, 0); + tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 1024, 128); + + //ui::window::registerWindow(SDL_GetWindowID(win), handleEvent); + } + refresh(); +} + + +void zx_128pageviewer::refresh() +{ + if (!win) return; + + Uint32 *pixels; + int pitch; + const uint8_t *tags = z80mem::get()->rawTagPtr(0); + SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch); + for (int i=0; i<131072; ++i) + { + const int x = (i&0x7f) + (((i>>14)&0x07)*128); + const int y = (i>>7)&0x7f; + uint32_t none_color = 0x808080; //i<0x4000 ? 0x101010 : i<0x5800 ? 0x202020 : i<0x5b00 ? 0x404040 : 0x808080; + uint8_t tag = tags[i]; + pixels[x+y*1024] = !(tag & MEMTAG_TOUCHED) ? none_color : (tag & MEMTAG_TINST) ? 0x00FF00 : (tag & MEMTAG_TREPEAT) ? 0xFF0000 : 0x0000FF; + } + //pixels[z80::getPC()] = 0xFFFFFF; + + SDL_UnlockTexture(tex); + SDL_RenderCopy(ren, tex, NULL, NULL); + SDL_RenderPresent(ren); +} + +void zx_128pageviewer::hide() +{ + //ui::window::unregisterWindow(SDL_GetWindowID(win)); + SDL_DestroyTexture(tex); tex = nullptr; + SDL_DestroyRenderer(ren); ren = nullptr; + SDL_DestroyWindow(win); win = nullptr; +} + +void zx_128pageviewer::focus() +{ + if (win) { + SDL_RaiseWindow(win); + refresh(); + } +} + +bool zx_128pageviewer::handleEvent(SDL_Event *e) +{ + return true; +} diff --git a/zx_128pageviewer.h b/zx_128pageviewer.h new file mode 100644 index 0000000..df570c8 --- /dev/null +++ b/zx_128pageviewer.h @@ -0,0 +1,13 @@ +#pragma once +#include "z80viewer.h" + +class zx_128pageviewer : public z80viewer +{ + public: + void show(); + void refresh(); + void hide(); + void focus(); + + bool handleEvent(SDL_Event *e); +}; diff --git a/zx_48mem.cpp b/zx_48mem.cpp index fa1e612..1a9c6b3 100644 --- a/zx_48mem.cpp +++ b/zx_48mem.cpp @@ -62,4 +62,9 @@ uint32_t zx_48mem::getSize() uint8_t *zx_48mem::rawPtr(uint32_t address) { return &memory[address]; +} + +uint8_t *zx_48mem::rawTagPtr(uint32_t address) +{ + return &tags[address]; } \ No newline at end of file diff --git a/zx_48mem.h b/zx_48mem.h index 5309b20..4f2f6d1 100644 --- a/zx_48mem.h +++ b/zx_48mem.h @@ -22,6 +22,7 @@ class zx_48mem : public z80mem uint32_t getSize(); uint8_t *rawPtr(uint32_t address); + uint8_t *rawTagPtr(uint32_t address); protected: diff --git a/zx_ula.cpp b/zx_ula.cpp index b41c3cd..f862690 100644 --- a/zx_ula.cpp +++ b/zx_ula.cpp @@ -293,11 +293,11 @@ namespace zx_ula if (t_sound>=317) { t_sound-=317; samples_generated++; - if (samples_t >=z80::getClock()) { + /*if (samples_t >=z80::getClock()) { //printf("%i\n", samples_generated); samples_generated=0; samples_t = 0; - } + }*/ /*if (SDL_GetTicks()>=samples_time+1000) { printf("%i\n", samples_generated); samples_generated=0;