#include "display.h" #include #include "sm83.h" #include "ppu.h" #include #include "ui_window.h" #include "debug.h" #include "ui.h" namespace display { uint32_t palette[2][4] = { { 0xFFFFFF, 0xAAAAAA, 0x555555, 0x000000 }, { 0xA0AA05, 0x749527, 0x487F49, 0x2E4326/*0x1D6A6B*/ } }; SDL_Window *win = nullptr; SDL_Renderer *ren = nullptr; SDL_Texture *tex = nullptr; SDL_Texture *uitex = nullptr; uint8_t zoom = 3; uint8_t use_palette=1; bool fullscreen = false; int fullscreen_scale = 1; SDL_Rect dest_rect; bool eventHandler(SDL_Event *e) { if (e->type==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 (!debug::debugging()) { if (debug::paused()) { if (e->type == SDL_KEYDOWN) { if (e->key.keysym.scancode==SDL_SCANCODE_ESCAPE) { const uint8_t dt = sm83::step(); debug::cont(); ppu::refresh(dt); } } } else { if (e->type == SDL_KEYDOWN) { if (e->key.keysym.scancode==SDL_SCANCODE_ESCAPE) { debug::pause(); display::redraw(); } else if (e->key.keysym.scancode==SDL_SCANCODE_F1) { display::decZoom(); } else if (e->key.keysym.scancode==SDL_SCANCODE_F2) { display::incZoom(); } else if (e->key.keysym.scancode==SDL_SCANCODE_F3) { display::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(); } else if (e->key.keysym.scancode==SDL_SCANCODE_Q && e->key.keysym.mod & KMOD_CTRL) { return false; } } } } 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("Gameboy Screen", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 160*z, 144*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, 160, 144); uitex = ui::createtexture(ren); ui::window::registerWindow(SDL_GetWindowID(win), eventHandler); if (fullscreen) { int w, h; SDL_GetWindowSize(win, &w, &h); fullscreen_scale = h/144; dest_rect.w = 160 * fullscreen_scale; dest_rect.h = 144 * 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 = 160 * zoom; dest_rect.h = 144 * zoom; } focus(); } void init() { reinit(); } 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 *ppu_pixels = ppu::getpixels(); Uint32* pixels; int pitch; SDL_LockTexture(tex, NULL, (void**)&pixels, &pitch); for (int i=0; i<160*144;++i) *(pixels++) = palette[use_palette][ppu_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); // Pintem les ralles dels pixels if (zoom>2 || 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); SDL_Rect rect {0,0,160*zoom,144*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, "Gameboy Screen"); strcat(tmp, title); SDL_SetWindowTitle(win, tmp); } void setZoom(const int value) { if (fullscreen) return; if (value < 1) return; SDL_DisplayMode dm; SDL_GetCurrentDisplayMode(0, &dm); if (160*value > dm.w) return; if (144*value > dm.h) return; zoom = value; reinit(); } void incZoom() { if (fullscreen) return; setZoom(zoom+1); } void decZoom() { if (fullscreen) return; setZoom(zoom-1); } void toggleFullscreen() { fullscreen = !fullscreen; reinit(); } const bool getFullscreen() { return fullscreen; } }