217 lines
6.3 KiB
C++
217 lines
6.3 KiB
C++
#include "display.h"
|
|
#include <cstring>
|
|
#include "sm83.h"
|
|
#include "ppu.h"
|
|
#include <SDL2/SDL.h>
|
|
#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;
|
|
}
|
|
}
|