From f8cc8a4bb316651f4f62d3380f1f57571d66c5a4 Mon Sep 17 00:00:00 2001 From: AliceLR Date: Wed, 25 Oct 2023 15:56:20 -0600 Subject: [PATCH] Add renderer hook for DJGPP hardware SMZX mode. --- arch/djgpp/render_ega.c | 60 ++++++++++++++++++++++++----------------- src/graphics.c | 11 ++++++++ src/graphics.h | 2 ++ 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/arch/djgpp/render_ega.c b/arch/djgpp/render_ega.c index 1531ff446..95e68f6f7 100644 --- a/arch/djgpp/render_ega.c +++ b/arch/djgpp/render_ega.c @@ -72,9 +72,10 @@ struct ega_render_data unsigned char flags; unsigned char oldmode; unsigned short vbsel; + unsigned char curpages; + boolean is_ati_card; uint8_t lines; uint8_t offset; - unsigned char curpages; uint32_t x; uint32_t y; }; @@ -94,7 +95,7 @@ static void ega_set_page(int page) __dpmi_int(0x10, ®); } -static void ega_set_smzx(void) +static void ega_set_smzx(boolean is_ati) { // Super MegaZeux mode: // In a nutshell, this sets bit 6 of the VGA Mode Control Register. @@ -107,6 +108,13 @@ static void ega_set_smzx(void) // and require a weird horizontal pixel shift value - see below. outportb(0x3C0, 0x10); outportb(0x3C0, 0x4C); + + if(is_ati) + { + // set horizontal pixel shift to Undefined (0.5 pixels, in theory) + outportb(0x3C0, 0x13); + outportb(0x3C0, 0x01); + } } static void ega_set_16p(void) @@ -218,6 +226,14 @@ static void ega_vsync(void) ; } +static boolean ega_is_ati_card(void) +{ + // TODO: untested. + char ati_magic[9]; + dosmemget(0xC0031, 9, ati_magic); + return memcmp("761295520", ati_magic, 9) == 0; +} + static boolean ega_init_video(struct graphics_data *graphics, struct config_info *conf) { @@ -256,6 +272,8 @@ static boolean ega_init_video(struct graphics_data *graphics, render_data->flags = 0; render_data->oldmode = ega_get_mode(); + render_data->is_ati_card = ega_is_ati_card(); + render_data->smzx_swap_nibbles = render_data->is_ati_card; graphics->render_data = render_data; return set_video_mode(); @@ -272,23 +290,12 @@ static void ega_free_video(struct graphics_data *graphics) free(render_data); } -static boolean ega_is_ati_card(void) -{ - // TODO: I don't know if this actually works! - char ati_magic[9]; - dosmemget(0xC0031, 9, ati_magic); - return memcmp("761295520", ati_magic, 9) == 0; -} - -static boolean ega_set_video_mode(struct graphics_data *graphics, - int width, int height, int depth, boolean fullscreen, boolean resize) +static boolean ega_set_screen_mode(struct graphics_data *graphics, unsigned mode) { struct ega_render_data *render_data = graphics->render_data; int i; - boolean ati_card = ega_is_ati_card(); render_data->page = 0; - render_data->smzx_swap_nibbles = ati_card; render_data->lines = 255; render_data->offset = 255; render_data->x = 65535; @@ -298,16 +305,8 @@ static boolean ega_set_video_mode(struct graphics_data *graphics, ega_set_14p(); ega_set_mode(0x03); - if(graphics->screen_mode) - { - ega_set_smzx(); - if(ati_card) - { - // set horizontal pixel shift to Undefined (0.5 pixels, in theory) - outportb(0x3C0, 0x13); - outportb(0x3C0, 0x01); - } - } + if(mode > 0) + ega_set_smzx(render_data->is_ati_card); ega_blink_off(); ega_cursor_off(); @@ -326,6 +325,18 @@ static boolean ega_set_video_mode(struct graphics_data *graphics, render_data->flags |= TEXT_FLAGS_CHR; + // Unless someone makes a cursed VGA card specifically for MegaZeux, + // mode 3 does not exist in hardware and never has. + if(mode > 2) + return false; + + return true; +} + +static boolean ega_set_video_mode(struct graphics_data *graphics, + int width, int height, int depth, boolean fullscreen, boolean resize) +{ + ega_set_screen_mode(graphics, graphics->screen_mode); return true; } @@ -497,6 +508,7 @@ void render_ega_register(struct renderer *renderer) renderer->init_video = ega_init_video; renderer->free_video = ega_free_video; renderer->set_video_mode = ega_set_video_mode; + renderer->set_screen_mode = ega_set_screen_mode; renderer->update_colors = ega_update_colors; renderer->resize_screen = resize_screen_standard; renderer->remap_char_range = ega_remap_char_range; diff --git a/src/graphics.c b/src/graphics.c index d05035b82..fd8722cc4 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -984,6 +984,7 @@ void set_screen_mode(unsigned int mode) fix_layer_screen_mode(); graphics.palette_dirty = true; + graphics.smzx_dirty = true; } unsigned int get_screen_mode(void) @@ -1112,6 +1113,16 @@ void update_screen(void) graphics.cursor_timestamp = ticks; } + if(graphics.smzx_dirty) + { + /* Request an SMZX mode change from the renderer, if applicable (EGA). + * Hardware SMZX may reset various text mode settings, so do it first. + */ + graphics.smzx_dirty = false; + if(graphics.renderer.set_screen_mode) + graphics.renderer.set_screen_mode(&graphics, graphics.screen_mode); + } + if(graphics.palette_dirty) { update_palette(); diff --git a/src/graphics.h b/src/graphics.h index 3e67ecfc7..020af8266 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -120,6 +120,7 @@ struct renderer void (*free_video) (struct graphics_data *); boolean (*set_video_mode) (struct graphics_data *, int width, int height, int depth, boolean fullscreen, boolean resize); + boolean (*set_screen_mode) (struct graphics_data *, unsigned mode); void (*update_colors) (struct graphics_data *, struct rgb_color *palette, unsigned int count); void (*resize_screen) (struct graphics_data *, int width, int height); @@ -178,6 +179,7 @@ struct graphics_data boolean renderer_is_headless; boolean default_smzx_loaded; boolean palette_dirty; + boolean smzx_dirty; boolean fade_status; boolean dialog_fade_status; boolean requires_extended;