diff --git a/src/86box.c b/src/86box.c index 16c99851a..6fb7541a7 100644 --- a/src/86box.c +++ b/src/86box.c @@ -175,6 +175,7 @@ int scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */ int config_changed; /* config has changed */ int title_update; int framecountx = 0; +int hard_reset_pending = 0; int unscaled_size_x = SCREEN_RES_X; /* current unscaled size X */ @@ -856,9 +857,7 @@ pc_reset_hard_init(void) void pc_reset_hard(void) { - pc_reset_hard_close(); - - pc_reset_hard_init(); + hard_reset_pending = 1; } @@ -936,6 +935,13 @@ pc_run(void) { wchar_t temp[200]; + /* Trigger a hard reset if one is pending. */ + if (hard_reset_pending) { + hard_reset_pending = 0; + pc_reset_hard_close(); + pc_reset_hard_init(); + } + /* Run a block of code. */ startblit(); cpu_exec(cpu_s->rspeed / 100); diff --git a/src/chipset/via_pipc.c b/src/chipset/via_pipc.c index 8202302e3..d488035ee 100644 --- a/src/chipset/via_pipc.c +++ b/src/chipset/via_pipc.c @@ -834,7 +834,7 @@ pipc_write(int func, int addr, uint8_t val, void *priv) } } else if (func == pm_func) { /* Power */ /* Read-only addresses */ - if ((addr < 0xd) || ((addr >= 0xe) && (addr < 0x40)) || (addr == 0x43) || + if ((addr < 0xd) || ((addr >= 0xe) && (addr < 0x40)) || (addr == 0x43) || (addr == 0x4a) || (addr == 0x4b) || (addr == 0x4e) || (addr == 0x4f) || (addr == 0x56) || (addr == 0x57) || ((addr >= 0x5c) && (addr < 0x61)) || ((addr >= 0x64) && (addr < 0x70)) || (addr == 0x72) || (addr == 0x73) || ((addr >= 0x75) && (addr < 0x80)) || (addr == 0x83) || ((addr >= 0x85) && (addr < 0x90)) || ((addr >= 0x92) && (addr < 0xd2)) || (addr >= 0xd7)) @@ -848,10 +848,20 @@ pipc_write(int func, int addr, uint8_t val, void *priv) switch (addr) { case 0x41: case 0x48: case 0x49: + if (addr == 0x48) { + if (dev->local >= VIA_PIPC_596A) + val = (val & 0x80) | 0x01; + else + val = 0x01; + } + dev->power_regs[addr] = val; c = (dev->power_regs[0x49] << 8); if (dev->local >= VIA_PIPC_596A) c |= (dev->power_regs[0x48] & 0x80); + /* Workaround for P3V133 BIOS in 596B mode mapping ACPI to E800 (same as SMBus) instead of E400. */ + if ((dev->local == VIA_PIPC_596B) && (c == ((dev->power_regs[0x91] << 8) | (dev->power_regs[0x90] & 0xf0))) && (dev->power_regs[0xd2] & 0x01)) + c -= 0x400; acpi_set_timer32(dev->acpi, dev->power_regs[0x41] & 0x08); acpi_update_io_mapping(dev->acpi, c, dev->power_regs[0x41] & 0x80); break; diff --git a/src/include/86box/language.h b/src/include/86box/language.h index b5e7a4304..006bc2312 100644 --- a/src/include/86box/language.h +++ b/src/include/86box/language.h @@ -115,6 +115,7 @@ #define IDS_2139 2139 // "MO images (*.IM?)\0*.IM?..." #define IDS_2140 2140 // "CD-ROM images (*.ISO;*.CU.." #define IDS_2141 2141 // "%hs Device Configuration" +#define IDS_2142 2142 // "Monitor in sleep mode" #define IDS_4096 4096 // "Hard disk (%s)" #define IDS_4097 4097 // "%01i:%01i" @@ -222,7 +223,7 @@ #define IDS_LANG_ENUS IDS_7168 -#define STR_NUM_2048 94 +#define STR_NUM_2048 95 #define STR_NUM_3072 11 #define STR_NUM_4096 39 #define STR_NUM_4352 6 diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index ff1a7c985..018c824a5 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -135,6 +135,7 @@ typedef struct svga_t plane_mask, writemask, colourcompare, colournocare, dac_mask, dac_status, + dpms, dpms_ui, ksc5601_sbyte_mask, ksc5601_udc_area_msb[2]; int ksc5601_swap_mode; diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index ed554309b..0d816ba7f 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -2282,6 +2282,7 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) svga->fb_only = 1; else svga->fb_only = 0; + svga->dpms = !!(mach64->crtc_gen_cntl & 0x0c); svga_recalctimings(&mach64->svga); break; diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 1d42f4a2d..6a3331b1d 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -910,6 +910,13 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) gd54xx_update_overlay(gd54xx); break; + case 0x0e: + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) { + svga->dpms = (val & 0x06) && ((svga->miscout & ((val & 0x06) << 5)) != 0xc0); + svga_recalctimings(svga); + } + break; + case 0x10: gd543x_mmio_write(0xb8001, val, gd54xx); break; diff --git a/src/video/vid_ddc.c b/src/video/vid_ddc.c index d7daefb2e..6fc8276e4 100644 --- a/src/video/vid_ddc.c +++ b/src/video/vid_ddc.c @@ -148,7 +148,7 @@ ddc_init(void *i2c) edid->input_params = 0x0e; /* analog input; separate sync; composite sync; sync on green */ edid->horiz_size = horiz_mm / 10; edid->vert_size = vert_mm / 10; - edid->features = 0x0b; /* RGB color; first timing is preferred; GTF/CVT */ + edid->features = 0xeb; /* DPMS standby/suspend/active-off; RGB color; first timing is preferred; GTF/CVT */ edid->red_green_lsb = 0x81; edid->blue_white_lsb = 0xf1; diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index 5a1d7a4b5..8ac16f2d6 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -691,6 +691,8 @@ mystique_out(uint16_t addr, uint8_t val, void *p) case 0x3df: if (mystique->crtcext_idx < 6) mystique->crtcext_regs[mystique->crtcext_idx] = val; + if (mystique->crtcext_idx == 1) + svga->dpms = !!(val & 0x30); if (mystique->crtcext_idx < 4) { svga->fullchange = changeframecount; svga_recalctimings(svga); diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 33f4a217e..fae21a279 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -2172,6 +2172,16 @@ s3_out(uint16_t addr, uint8_t val, void *p) } else if (svga->seqaddr == 0xa) { svga->seqregs[svga->seqaddr] = val & 0x80; return; + } else if (s3->chip >= S3_VISION964) { + if (svga->seqaddr == 0x08) { + svga->seqregs[svga->seqaddr] = val & 0x0f; + return; + } else if ((svga->seqaddr == 0x0d) && (svga->seqregs[0x08] == 0x06)) { + svga->seqregs[svga->seqaddr] = val; + svga->dpms = ((s3->chip >= S3_VISION964) && (svga->seqregs[0x0d] & 0x50)) || (svga->crtc[0x56] & ((s3->chip >= S3_TRIO32) ? 0x06 : 0x20)); + svga_recalctimings(svga); + return; + } } break; @@ -2376,6 +2386,11 @@ s3_out(uint16_t addr, uint8_t val, void *p) } break; + case 0x56: + svga->dpms = ((s3->chip >= S3_VISION964) && (svga->seqregs[0x0d] & 0x50)) || (svga->crtc[0x56] & ((s3->chip >= S3_TRIO32) ? 0x06 : 0x20)); + old = ~val; /* force recalc */ + break; + case 0x67: if (s3->chip >= S3_TRIO32) { switch (val >> 4) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index bf7b64029..4b37eda62 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -428,6 +428,14 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) svga->write_bank = svga->read_bank = virge->bank << 16; else svga->write_bank = svga->read_bank = virge->bank << 14; + } else if (svga->seqaddr == 0x08) { + svga->seqregs[svga->seqaddr] = val & 0x0f; + return; + } else if ((svga->seqaddr == 0x0d) && (svga->seqregs[0x08] == 0x06)) { + svga->seqregs[svga->seqaddr] = val; + svga->dpms = (svga->seqregs[0x0d] & 0x50) || (svga->crtc[0x56] & 0x06); + svga_recalctimings(svga); + return; } break; @@ -543,6 +551,11 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) case 0x58: case 0x59: case 0x5a: s3_virge_updatemapping(virge); break; + + case 0x56: + svga->dpms = (svga->seqregs[0x0d] & 0x50) || (svga->crtc[0x56] & 0x06); + old = ~val; /* force recalc */ + break; case 0x67: switch (val >> 4) diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index f641d0bb2..de84df1f0 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -34,6 +34,8 @@ #include <86box/pit.h> #include <86box/mem.h> #include <86box/rom.h> +#include <86box/plat.h> +#include <86box/ui.h> #include <86box/video.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> @@ -574,12 +576,29 @@ svga_recalctimings(svga_t *svga) svga->dispontime = TIMER_USEC; if (svga->dispofftime < TIMER_USEC) svga->dispofftime = TIMER_USEC; + + /* Inform the user interface of any DPMS mode changes. */ + if (svga->dpms) { + if (!svga->dpms_ui) { + svga->dpms_ui = 1; + ui_sb_set_text_w(plat_get_string(IDS_2142)); + } + } else if (svga->dpms_ui) { + svga->dpms_ui = 0; + ui_sb_set_text_w(NULL); + } } static void svga_do_render(svga_t *svga) { + /* Always render a blank screen and nothing else while in DPMS mode. */ + if (svga->dpms) { + svga_render_blank(svga); + return; + } + if (!svga->override) { svga->render(svga); @@ -963,6 +982,9 @@ svga_close(svga_t *svga) free(svga->changedvram); free(svga->vram); + if (svga->dpms_ui) + ui_sb_set_text_w(NULL); + svga_pri = NULL; } @@ -1361,7 +1383,10 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) } else suppress_overscan = 0; - set_screen_size(xsize + x_add, ysize + y_add); + /* Block resolution changes while in DPMS mode to avoid getting a bogus + screen width (320). We're already rendering a blank screen anyway. */ + if (!svga->dpms) + set_screen_size(xsize + x_add, ysize + y_add); if (video_force_resize_get()) video_force_resize_set(0); diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 5d5e1c892..7083c10ee 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -678,6 +678,8 @@ static void banshee_ext_outl(uint16_t addr, uint32_t val, void *p) case DAC_dacMode: banshee->dacMode = val; + svga->dpms = !!(val & 0x0a); + svga_recalctimings(svga); break; case DAC_dacAddr: banshee->dacAddr = val & 0x1ff; diff --git a/src/win/86Box.rc b/src/win/86Box.rc index da174a4fa..c9dd1e072 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -1076,6 +1076,7 @@ BEGIN IDS_2139 "MO images (*.IM?;*.MDI)\0*.IM?;*.MDI\0All files (*.*)\0*.*\0" IDS_2140 "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0" IDS_2141 "%hs Device Configuration" + IDS_2142 "Monitor in sleep mode" END STRINGTABLE DISCARDABLE diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index e2a768570..ea7be0212 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -72,6 +72,8 @@ static int sb_ready = 0; static uint8_t sb_map[256]; static int dpi = 96; static int icon_width = 24; +static wchar_t sb_text[512] = L"\0"; +static wchar_t sb_bugtext[512] = L"\0"; /* Also used by win_settings.c */ intptr_t @@ -424,6 +426,11 @@ StatusBarDestroyTips(void) void ui_sb_set_ready(int ready) { + if (ready == 0) { + ui_sb_bugui(NULL); + ui_sb_set_text(NULL); + } + sb_ready = ready; } @@ -941,9 +948,8 @@ StatusBarCreate(HWND hwndParent, uintptr_t idStatus, HINSTANCE hInst) } -/* API */ -void -ui_sb_set_text_w(wchar_t *wstr) +static void +ui_sb_update_text() { uint8_t part = 0xff; @@ -953,7 +959,19 @@ ui_sb_set_text_w(wchar_t *wstr) part = sb_map[SB_TEXT]; if (part != 0xff) - SendMessage(hwndSBAR, SB_SETTEXT, part | SBT_NOBORDERS, (LPARAM)wstr); + SendMessage(hwndSBAR, SB_SETTEXT, part | SBT_NOBORDERS, (LPARAM)((sb_text[0] != L'\0') ? sb_text : sb_bugtext)); +} + + +/* API */ +void +ui_sb_set_text_w(wchar_t *wstr) +{ + if (wstr) + wcscpy(sb_text, wstr); + else + memset(sb_text, 0x00, sizeof(sb_text)); + ui_sb_update_text(); } @@ -961,11 +979,11 @@ ui_sb_set_text_w(wchar_t *wstr) void ui_sb_set_text(char *str) { - static wchar_t wstr[512]; - - memset(wstr, 0x00, sizeof(wstr)); - mbstowcs(wstr, str, strlen(str) + 1); - ui_sb_set_text_w(wstr); + if (str) + mbstowcs(sb_text, str, strlen(str) + 1); + else + memset(sb_text, 0x00, sizeof(sb_text)); + ui_sb_update_text(); } @@ -973,9 +991,9 @@ ui_sb_set_text(char *str) void ui_sb_bugui(char *str) { - static wchar_t wstr[512]; - - memset(wstr, 0x00, sizeof(wstr)); - mbstowcs(wstr, str, strlen(str) + 1); - ui_sb_set_text_w(wstr); + if (str) + mbstowcs(sb_bugtext, str, strlen(str) + 1); + else + memset(sb_bugtext, 0x00, sizeof(sb_bugtext)); + ui_sb_update_text(); }