mirror of
https://github.com/kichikuou/system3-sdl2.git
synced 2026-10-03 20:38:13 +03:00
Scanline screen effect
It can be activated by the -scanline command line flag, system3.ini, or the menubar on Windows. Effective especially for games with 200-line screen mode, such as Little Vampire and Intruder.
This commit is contained in:
@@ -104,6 +104,8 @@ Config::Config(int argc, char *argv[])
|
||||
title = argv[++i];
|
||||
else if (strcmp(argv[i], "-timiditycfg") == 0)
|
||||
timidity_cfg = argv[++i];
|
||||
else if (strcmp(argv[i], "-scanline") == 0)
|
||||
scanline = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +160,8 @@ void Config::load_ini()
|
||||
title = val;
|
||||
else if (!strcasecmp(key, "timiditycfg"))
|
||||
timidity_cfg = normalize_path(val);
|
||||
else if (!strcasecmp(key, "scanline"))
|
||||
scanline = to_bool(val, lineno);
|
||||
else
|
||||
WARNING(INIFILENAME ":%d unknown key '%s'", lineno, key);
|
||||
} else if (current_section == STRING) {
|
||||
|
||||
@@ -31,6 +31,7 @@ struct Config {
|
||||
std::string timidity_cfg;
|
||||
bool use_fm = false;
|
||||
bool no_antialias = false;
|
||||
bool scanline = false;
|
||||
|
||||
private:
|
||||
void load_ini();
|
||||
|
||||
@@ -36,6 +36,28 @@ static SDL_Surface* display_surface;
|
||||
box[n].ey = y2; \
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32 SCANLINE_ALPHA = 0x38; // 0-255
|
||||
|
||||
SDL_Texture* create_scanline_texture(SDL_Renderer* renderer, int width, int height)
|
||||
{
|
||||
SDL_Surface* sf = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_ARGB8888);
|
||||
for (int y = 0; y < height; y++) {
|
||||
uint32* p = surface_line(sf, y);
|
||||
uint32 v = y % 2 ? (SCANLINE_ALPHA << 24) : 0;
|
||||
for (int x = 0; x < width; x++) {
|
||||
p[x] = v;
|
||||
}
|
||||
}
|
||||
SDL_Texture* tx = SDL_CreateTextureFromSurface(renderer, sf);
|
||||
SDL_SetTextureBlendMode(tx, SDL_BLENDMODE_BLEND);
|
||||
SDL_FreeSurface(sf);
|
||||
return tx;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false)
|
||||
{
|
||||
// 画面サイズ
|
||||
@@ -52,6 +74,7 @@ AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false)
|
||||
SDL_SetWindowSize(g_window, window_width, window_height);
|
||||
SDL_RenderSetLogicalSize(g_renderer, window_width, window_height);
|
||||
sdlTexture = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, screen_width, screen_height); // TOOD: pixelformat?
|
||||
scanline_texture = NULL;
|
||||
|
||||
// DIBSection 8bpp * 3 (表, 裏, メニュー)
|
||||
for(int i = 0; i < 3; i++) {
|
||||
@@ -358,6 +381,8 @@ AGS::AGS(NACT* parent, const Config& config) : nact(parent), dirty(false)
|
||||
// マウスカーソル
|
||||
cursor_color = 15;
|
||||
cursor_index = 0;
|
||||
|
||||
set_scanline_mode(config.scanline);
|
||||
}
|
||||
|
||||
AGS::~AGS()
|
||||
@@ -527,10 +552,26 @@ void AGS::update_screen()
|
||||
SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255);
|
||||
SDL_SetRenderDrawBlendMode(g_renderer, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
if (scanline_texture)
|
||||
SDL_RenderCopy(g_renderer, scanline_texture, NULL, NULL);
|
||||
SDL_RenderPresent(g_renderer);
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
void AGS::set_scanline_mode(bool enable)
|
||||
{
|
||||
if (enable && !scanline_texture) {
|
||||
scanline_texture = create_scanline_texture(g_renderer, screen_width, screen_height);
|
||||
dirty = true;
|
||||
update_screen();
|
||||
} else if (!enable && scanline_texture) {
|
||||
SDL_DestroyTexture(scanline_texture);
|
||||
scanline_texture = NULL;
|
||||
dirty = true;
|
||||
update_screen();
|
||||
}
|
||||
}
|
||||
|
||||
void AGS::save_screenshot(const char* path)
|
||||
{
|
||||
SDL_Surface* sf = SDL_CreateRGBSurface(0, screen_width, screen_height, 32, 0, 0, 0, 0);
|
||||
@@ -539,6 +580,14 @@ void AGS::save_screenshot(const char* path)
|
||||
SDL_BlitSurface(hBmpDest, &r, sf, NULL);
|
||||
SDL_LockSurface(hBmpDest);
|
||||
|
||||
if (scanline_texture) {
|
||||
SDL_Renderer* renderer = SDL_CreateSoftwareRenderer(sf);
|
||||
SDL_Texture *tx = create_scanline_texture(renderer, screen_width, screen_height);
|
||||
SDL_RenderCopy(renderer, tx, NULL, NULL);
|
||||
SDL_DestroyTexture(tx);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
}
|
||||
|
||||
if (SDL_SaveBMP(sf, path) != 0) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "system3",
|
||||
SDL_GetError(), g_window);
|
||||
|
||||
@@ -40,6 +40,7 @@ protected:
|
||||
NACT* nact;
|
||||
private:
|
||||
SDL_Texture* sdlTexture;
|
||||
SDL_Texture* scanline_texture;
|
||||
|
||||
// Surface
|
||||
SDL_Surface* hBmpScreen[3]; // 8bpp * 3 (表, 裏, メニュー)
|
||||
@@ -128,6 +129,8 @@ public:
|
||||
void select_cursor();
|
||||
void translate_mouse_coords(int* x, int* y);
|
||||
|
||||
bool get_scanline_mode() const { return scanline_texture; }
|
||||
void set_scanline_mode(bool enable);
|
||||
void save_screenshot(const char* path);
|
||||
int calculate_menu_max(int window);
|
||||
|
||||
|
||||
@@ -21,13 +21,15 @@ HWND get_hwnd(SDL_Window* window) {
|
||||
return info.info.win.window;
|
||||
}
|
||||
|
||||
void init_menu(bool mouse_move_enabled)
|
||||
void init_menu(bool mouse_move_enabled, bool scanline_enabled)
|
||||
{
|
||||
HINSTANCE hinst = (HINSTANCE)GetModuleHandle(NULL);
|
||||
HMENU hmenu = LoadMenu(hinst, MAKEINTRESOURCE(IDR_MENU1));
|
||||
SetMenu(get_hwnd(g_window), hmenu);
|
||||
if (mouse_move_enabled)
|
||||
CheckMenuItem(hmenu, ID_OPTION_MOUSE_MOVE, MF_BYCOMMAND | MFS_CHECKED);
|
||||
if (scanline_enabled)
|
||||
CheckMenuItem(hmenu, ID_SCANLINE, MF_BYCOMMAND | MFS_CHECKED);
|
||||
}
|
||||
|
||||
void init_console(int sys_ver)
|
||||
@@ -129,7 +131,7 @@ void NACT::text_dialog()
|
||||
|
||||
void NACT::platform_initialize()
|
||||
{
|
||||
init_menu(mouse_move_enabled);
|
||||
init_menu(mouse_move_enabled, config.scanline);
|
||||
init_console(sys_ver);
|
||||
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
|
||||
}
|
||||
@@ -188,6 +190,11 @@ bool NACT::handle_platform_event(const SDL_Event& e)
|
||||
SDL_SetWindowFullscreen(g_window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
ags->flush_screen(true);
|
||||
break;
|
||||
case ID_SCANLINE:
|
||||
ags->set_scanline_mode(!ags->get_scanline_mode());
|
||||
CheckMenuItem(GetMenu(get_hwnd(g_window)), ID_SCANLINE, MF_BYCOMMAND |
|
||||
ags->get_scanline_mode() ? MFS_CHECKED : MFS_UNCHECKED);
|
||||
break;
|
||||
case ID_OPTION_MOUSE_MOVE:
|
||||
mouse_move_enabled = !mouse_move_enabled;
|
||||
CheckMenuItem(GetMenu(get_hwnd(g_window)), ID_OPTION_MOUSE_MOVE,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define ID_EXIT 40002
|
||||
#define ID_SCREEN_WINDOW 40010
|
||||
#define ID_SCREEN_FULL 40011
|
||||
#define ID_SCANLINE 40012
|
||||
#define ID_OPTION_MOUSE_MOVE 40020
|
||||
#define ID_OPTION_FM 40021
|
||||
#define ID_OPTION_MIDI 40022
|
||||
|
||||
@@ -97,6 +97,8 @@ BEGIN
|
||||
BEGIN
|
||||
MENUITEM "Window", ID_SCREEN_WINDOW
|
||||
MENUITEM "Fullscreen", ID_SCREEN_FULL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Scanline effect", ID_SCANLINE
|
||||
END
|
||||
POPUP "Option"
|
||||
BEGIN
|
||||
@@ -153,6 +155,8 @@ BEGIN
|
||||
BEGIN
|
||||
MENUITEM "ウィンドウ", ID_SCREEN_WINDOW
|
||||
MENUITEM "フルスクリーン", ID_SCREEN_FULL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "走査線エフェクト", ID_SCANLINE
|
||||
END
|
||||
POPUP "オプション"
|
||||
BEGIN
|
||||
@@ -209,6 +213,8 @@ BEGIN
|
||||
BEGIN
|
||||
MENUITEM "窗口化", ID_SCREEN_WINDOW
|
||||
MENUITEM "全屏化", ID_SCREEN_FULL
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Scanline effect", ID_SCANLINE
|
||||
END
|
||||
POPUP "选项"
|
||||
BEGIN
|
||||
|
||||
Reference in New Issue
Block a user