diff --git a/debug.cpp b/debug.cpp index f1bbc05..8c77011 100644 --- a/debug.cpp +++ b/debug.cpp @@ -510,14 +510,10 @@ namespace debug const uint8_t flags = (sm83::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) ); + ui::printtxt(1,5,"Z", flags&0x80 ? (mod_flags&0x80 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x80 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(6,5,"N", flags&0x40 ? (mod_flags&0x40 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x40 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(3,5,"H", flags&0x20 ? (mod_flags&0x20 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x20 ? COLOR_BROWN : COLOR_GRAY) ); + ui::printtxt(7,5,"C", flags&0x10 ? (mod_flags&0x10 ? COLOR_RED : COLOR_WHITE) : (mod_flags&0x10 ? COLOR_BROWN : COLOR_GRAY) ); // STACK diff --git a/gbscreen.cpp b/gbscreen.cpp new file mode 100644 index 0000000..cb7bec0 --- /dev/null +++ b/gbscreen.cpp @@ -0,0 +1,374 @@ +#include "gbscreen.h" +#include "sm83.h" +#include "mem.h" +//#include "zx_ula.h" +#include +#include "ui_window.h" +#include "debug.h" +#include "ui.h" + +namespace zxscreen +{ + uint32_t palette[4] = { + 0xFFFFFF, 0xAAAAAA, 0x555555, 0x000000 + }; + SDL_Window *win = nullptr; + SDL_Renderer *ren = nullptr; + SDL_Texture *tex = nullptr; + SDL_Texture *uitex = nullptr; + + uint32_t t_states_total = 69888; + uint32_t t_states_per_scanline = 224; + uint32_t vsync_lines = 16; + + uint8_t zoom = 1; + bool fullscreen = false; + bool full_refresh = true; + int fullscreen_scale = 1; + SDL_Rect dest_rect; + + uint32_t time=0; + + uint32_t t_screen = 0; + uint8_t t_flash = 0; + bool flash = false; + + int pixels_draw = 0; + + uint16_t pixel_base_addr = 0x4000; + uint16_t color_base_addr = 0x5800; + + uint16_t *pixel_addr = nullptr; //[69888]; + uint16_t *color_addr = nullptr; //[69888]; + uint8_t zx_pixels[352*296]; + uint8_t *ptr_pixel = zx_pixels; + + #define SCREEN_SYNC 0xFFFF + #define SCREEN_BORDER 0xFFFE + + void create_tables() + { + uint32_t count = 0; + + if (pixel_addr) free(pixel_addr); + if (color_addr) free(color_addr); + pixel_addr = (uint16_t*)malloc(t_states_total*sizeof(uint16_t)); + color_addr = (uint16_t*)malloc(t_states_total*sizeof(uint16_t)); + + uint16_t *ptr_pixel = pixel_addr; + uint16_t *ptr_color = color_addr; + + // vsync + for (int i=0; i>3)*32; + uint16_t address = /*0x4000 |*/ (x&0x1f) | ((y&0x7)<<8) | ((y&0x38)<<2) | ((y&0xc0)<<5); + for (int i=7;i>0;i-=2) + { + *(ptr_pixel++) = (address & 0x1FFF) | (i << 13); + *(ptr_color++) = color; + count+=2; + } + } + + // Right border + for (int j=0;j<24;++j) { *(ptr_pixel++) = 0; *(ptr_color++) = SCREEN_BORDER; count+=2; } + } + + // Lower border + for (int i=0; i<56;++i) { + // hsync + for (int j=0;jtype==SDL_WINDOWEVENT) { + if (e->window.event==SDL_WINDOWEVENT_CLOSE) { + return false; + } else if ((e->window.event==SDL_WINDOWEVENT_SHOWN) || (e->window.event==SDL_WINDOWEVENT_EXPOSED)) { + redraw(); + } + } + if (!z80debug::debugging()) { + if (z80debug::paused()) { + if (e->type == SDL_KEYDOWN) { + if (e->key.keysym.scancode==SDL_SCANCODE_ESCAPE) { + const uint8_t dt = z80::step(); + z80debug::cont(); + zxscreen::refresh(dt); + } + } + } else { + if (e->type == SDL_KEYDOWN) { + if (e->key.keysym.scancode==SDL_SCANCODE_ESCAPE) { + z80debug::pause(); + zxscreen::redraw(); + } else if (e->key.keysym.scancode==SDL_SCANCODE_F1) { + zxscreen::decZoom(); + } else if (e->key.keysym.scancode==SDL_SCANCODE_F2) { + zxscreen::incZoom(); + } else if (e->key.keysym.scancode==SDL_SCANCODE_F3) { + zxscreen::toggleFullscreen(); + } else if (e->key.keysym.scancode==SDL_SCANCODE_F6) { + zx_tape::play(); + } else if (e->key.keysym.scancode==SDL_SCANCODE_F7) { + zx_tape::rewind(); + } + } + } + } + if (e->type == SDL_MOUSEMOTION) { + SDL_ShowCursor(true); + } + return true; + } + + void reinit() + { + 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("ZX Spectrum Screen", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 352*z, 296*z, fullscreen?SDL_WINDOW_FULLSCREEN_DESKTOP:SDL_WINDOW_SHOWN); + ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); + tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 352, 296); + uitex = ui::createtexture(ren); + + ui::window::registerWindow(SDL_GetWindowID(win), eventHandler); + + if (fullscreen) + { + int w, h; + SDL_GetWindowSize(win, &w, &h); + fullscreen_scale = h/296; + dest_rect.w = 352 * fullscreen_scale; + dest_rect.h = 296 * 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 = 352 * zoom; + dest_rect.h = 296 * zoom; + } + + focus(); + } + + void setBaseAddresses(const uint32_t pixeladdr, const uint32_t coloraddr) + { + pixel_base_addr = pixeladdr; + color_base_addr = coloraddr; + } + + void init(int mode) + { + zxscreen::mode = mode; + if (mode==SCREEN_MODE_48K) { + setBaseAddresses(0x4000, 0x5800); + t_states_total = 69888; + t_states_per_scanline = 224; + vsync_lines = 16; + } else if (mode==SCREEN_MODE_128K) { + setBaseAddresses(0x14000, 0x15800); + t_states_total = 70908; + t_states_per_scanline = 228; + vsync_lines = 15; + } + + create_tables(); + reinit(); + } + + void focus() + { + if (win) + { + SDL_RaiseWindow(win); + redraw(); + } + } + + void refresh(const uint32_t dt, const bool full) + { + const uint8_t* pixel_mem = z80mem::get()->rawPtr(pixel_base_addr); + const uint8_t* color_mem = z80mem::get()->rawPtr(color_base_addr); + const uint8_t border_color = zx_ula::get_border_color(); + + for (int i=0;ireadMem(color_base_addr + color_addr[t_screen]); + uint8_t c1 = color&0x7, c2 = (color>>3)&0x7; + if ((color&0x80) && flash) { c1=c2; c2=color&0x7; } + if ((color&0x40)) { c1 |= 0x8; c2 |= 0x8; } + uint16_t address = /*(0x4000) |*/ (pixel_addr[t_screen]&0x1FFF); + uint8_t mask = 1 << (pixel_addr[t_screen]>>13); + uint8_t block = *(pixel_mem + address); // z80mem::get()->readMem(pixel_base_addr + address); + *(ptr_pixel++)=(block&mask) ? c1 : c2; + mask>>=1; + *(ptr_pixel++)=(block&mask) ? c1 : c2; + } + pixels_draw+=2; + } + t_screen++; + if (t_screen>=t_states_total) { + pixels_draw=0; + t_flash++; + if (t_flash==16) { t_flash=0; flash = !flash; } + t_screen=0; + ptr_pixel = zx_pixels; + redraw(); + if (!full) z80::interrupt(); + } + } + } + + void fullrefresh() + { + uint32_t tmp = t_screen; + t_screen = 0; + uint8_t * tmp_ptr = ptr_pixel; + ptr_pixel = zx_pixels; + refresh(t_states_total, true); + ptr_pixel = tmp_ptr; + t_screen = tmp; + } + + void debugrefresh(const uint32_t dt) + { + if (full_refresh) fullrefresh(); else refresh(dt); + } + + void redraw(const bool present) + { + if (zx_tape::getplaying() && zx_tape::getOption(ZXTAPE_OPTION_FAST_LOAD)) return; + + ui::setrenderer(ren, uitex); + + Uint32* pixels; + int pitch; + SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch); + for (int i=0; i<352*296;++i) *(pixels++) = palette[zx_pixels[i]]; + SDL_UnlockTexture(tex); + + if (fullscreen) + { + SDL_SetRenderDrawColor(ren, 0, 0, 0, 255); + SDL_RenderClear(ren); + } + + // Pintem la textura a pantalla + SDL_RenderCopy(ren, tex, NULL, &dest_rect); + + if (present) + SDL_RenderPresent(ren); + else + { + SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(ren, 0, 0, 0, 128); + SDL_Rect rect {0,0,352*zoom,296*zoom}; + if (fullscreen) SDL_GetWindowSize(win, &rect.w, &rect.h); + SDL_RenderFillRect(ren, &rect); + } + + } + + void present() + { + SDL_RenderPresent(ren); + } + + void setTitle(const char* title) + { + char tmp[256]; + strcpy(tmp, "ZX Spectrum Screen"); + strcat(tmp, title); + SDL_SetWindowTitle(win, tmp); + } + + void setZoom(const int value) + { + if (value < 1) return; + SDL_DisplayMode dm; + SDL_GetCurrentDisplayMode(0, &dm); + + if (352*value > dm.w) return; + if (296*value > dm.h) return; + + zoom = value; + reinit(); + } + + void incZoom() + { + setZoom(zoom+1); + } + + void decZoom() + { + setZoom(zoom-1); + } + + void toggleFullscreen() + { + fullscreen = !fullscreen; + reinit(); + } + + const bool getFullscreen() + { + return fullscreen; + } + + void toggleFullRefresh() + { + full_refresh = !full_refresh; + } + + const bool getFullRefresh() + { + return full_refresh; + } + + + SDL_Renderer *getrenderer() + { + return ren; + } +} diff --git a/gbscreen.h b/gbscreen.h new file mode 100644 index 0000000..ee7f72b --- /dev/null +++ b/gbscreen.h @@ -0,0 +1,25 @@ +#pragma once +#include + +namespace gbscreen +{ + void init(int mode); + void reinit(); + void focus(); + void refresh(const uint32_t dt, const bool full=false); + void fullrefresh(); + void debugrefresh(); + void redraw(const bool present=true); + void present(); + void setTitle(const char* title); + + void incZoom(); + void decZoom(); + void toggleFullscreen(); + const bool getFullscreen(); + + void toggleFullRefresh(); + const bool getFullRefresh(); + + SDL_Renderer *getrenderer(); +} diff --git a/sm83.cpp b/sm83.cpp index 799e230..69db0e0 100644 --- a/sm83.cpp +++ b/sm83.cpp @@ -334,7 +334,7 @@ namespace sm83 void RLA() { const bool should_carry = rA & 0x80; - rA = (rA<<1) | (rF&fC); + rA = (rA<<1) | ((rF&fC)>>4); rF = 0; if (should_carry) SET_FLAGS(fC); } @@ -342,7 +342,7 @@ namespace sm83 void RRA() { const bool should_carry = rA & 0x01; - rA = ((rF&fC)<<7) | (rA>>1); + rA = ((rF&fC)<<3) | (rA>>1); rF = 0; if (should_carry) SET_FLAGS(fC); } @@ -577,7 +577,7 @@ namespace sm83 static inline const uint8_t RL(const uint8_t v) { - const uint8_t res = (v<<1) | (rF&fC); + const uint8_t res = (v<<1) | ((rF&fC)>>4); rF=0; if (res==0) SET_FLAGS(fZ); if (v&0x80) SET_FLAGS(fC); @@ -586,7 +586,7 @@ namespace sm83 static inline const uint8_t RR(const uint8_t v) { - const uint8_t res = ((rF&fC)<<7) | (v>>1); + const uint8_t res = ((rF&fC)<<3) | (v>>1); rF=0; if (res==0) SET_FLAGS(fZ); if (v&1) SET_FLAGS(fC);