#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; } }