diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 4932b9494..72a66703f 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -279,7 +279,7 @@ resub_cycles(int old_cycles) if (old_cycles > cycles) { cyc_diff = old_cycles - cycles; cycles = old_cycles; - resub_cycles(cyc_diff); + sub_cycles(cyc_diff); } } @@ -298,27 +298,35 @@ cpu_io(int bits, int out, uint16_t port) if (out) { wait(4, 1); if (bits == 16) { - if (is8086 && !(port & 1)) + if (is8086 && !(port & 1)) { + old_cycles = cycles; outw(port, AX); - else { + } else { wait(4, 1); + old_cycles = cycles; outb(port++, AL); outb(port, AH); } - } else + } else { + old_cycles = cycles; outb(port, AL); + } } else { wait(4, 1); if (bits == 16) { - if (is8086 && !(port & 1)) + if (is8086 && !(port & 1)) { + old_cycles = cycles; AX = inw(port); - else { + } else { wait(4, 1); + old_cycles = cycles; AL = inb(port++); AH = inb(port); } - } else + } else { + old_cycles = cycles; AL = inb(port); + } } resub_cycles(old_cycles); diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index b15e4bd46..64ea5dd6f 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -808,8 +808,8 @@ void PUSHL(uint32_t v) { if (cpu_16bitbus) { - PUSHW(v & 0xffff); PUSHW(v >> 16); + PUSHW(v & 0xffff); } else { if (stack32) { writememl(ss, ESP - 4, v); diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index 627a293c6..297c60c99 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -152,6 +152,7 @@ extern void pclog_toggle_suppr(void); extern void pclog(const char *fmt, ...); extern void fatal(const char *fmt, ...); extern void set_screen_size(int x, int y); +extern void reset_screen_size(void); extern void set_screen_size_natural(void); #if 0 extern void pc_reload(wchar_t *fn); diff --git a/src/include/86box/rom.h b/src/include/86box/rom.h index ee9d9e95f..d06864ca0 100644 --- a/src/include/86box/rom.h +++ b/src/include/86box/rom.h @@ -49,6 +49,8 @@ extern FILE *rom_fopen(wchar_t *fn, wchar_t *mode); extern int rom_getfile(wchar_t *fn, wchar_t *s, int size); extern int rom_present(wchar_t *fn); +extern int rom_load_linear_oddeven(wchar_t *fn, uint32_t addr, int sz, + int off, uint8_t *ptr); extern int rom_load_linear(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr); extern int rom_load_interleaved(wchar_t *fnl, wchar_t *fnh, uint32_t addr, @@ -68,6 +70,8 @@ extern int bios_load_linear_combined2(wchar_t *fn1, wchar_t *fn2, extern int rom_init(rom_t *rom, wchar_t *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags); +extern int rom_init_oddeven(rom_t *rom, wchar_t *fn, uint32_t address, int size, + int mask, int file_offset, uint32_t flags); extern int rom_init_interleaved(rom_t *rom, wchar_t *fn_low, wchar_t *fn_high, uint32_t address, int size, int mask, int file_offset, diff --git a/src/include/86box/win.h b/src/include/86box/win.h index 4aceae0be..ceb06f1ba 100644 --- a/src/include/86box/win.h +++ b/src/include/86box/win.h @@ -55,6 +55,8 @@ DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); #define SB_CLASS_NAME L"86BoxStatusBar" #define SB_MENU_NAME L"StatusBarMenu" #define FS_CLASS_NAME L"86BoxFullScreen" +#define SDL_CLASS_NAME L"86BoxSDLWnd" +#define SDL_SUB_CLASS_NAME L"86BoxSDLSubWnd" #define FLOPPY_SUBMENU_NAME L"FloppySubmenu" #define CDROM_SUBMENU_NAME L"CdromSubmenu" @@ -155,7 +157,6 @@ extern int hard_disk_was_added(void); /* Platform UI support functions. */ extern int ui_init(int nCmdShow); -extern void plat_set_input(HWND h); /* Functions in win_about.c: */ diff --git a/src/include/86box/win_sdl.h b/src/include/86box/win_sdl.h index 4f6bca231..cc61142be 100644 --- a/src/include/86box/win_sdl.h +++ b/src/include/86box/win_sdl.h @@ -54,13 +54,10 @@ extern void sdl_close(void); extern int sdl_inits(HWND h); extern int sdl_inith(HWND h); extern int sdl_initho(HWND h); -extern int sdl_inits_fs(HWND h); -extern int sdl_inith_fs(HWND h); -extern int sdl_initho_fs(HWND h); extern int sdl_pause(void); extern void sdl_resize(int x, int y); extern void sdl_enable(int enable); -extern void sdl_reinit_texture(); +extern void sdl_set_fs(int fs); #endif /*WIN_SDL_H*/ diff --git a/src/mem/rom.c b/src/mem/rom.c index fc827539b..8e4eda437 100644 --- a/src/mem/rom.c +++ b/src/mem/rom.c @@ -162,6 +162,42 @@ rom_readl(uint32_t addr, void *priv) } +int +rom_load_linear_oddeven(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) +{ + FILE *f = rom_fopen(fn, L"rb"); + int i; + + if (f == NULL) { + rom_log("ROM: image '%ls' not found\n", fn); + return(0); + } + + /* Make sure we only look at the base-256K offset. */ + if (addr >= 0x40000) + addr = 0; + else + addr &= 0x03ffff; + + if (ptr != NULL) { + if (fseek(f, off, SEEK_SET) == -1) + fatal("rom_load_linear(): Error seeking to the beginning of the file\n"); + for (i = 0; i < (sz >> 1); i++) { + if (fread(ptr + (addr + (i << 1)), 1, 1, f) != 1) + fatal("rom_load_linear(): Error reading even data\n"); + } + for (i = 0; i < (sz >> 1); i++) { + if (fread(ptr + (addr + (i << 1) + 1), 1, 1, f) != 1) + fatal("rom_load_linear(): Error reading od data\n"); + } + } + + (void)fclose(f); + + return(1); +} + + /* Load a ROM BIOS from its chips, interleaved mode. */ int rom_load_linear(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) @@ -507,6 +543,36 @@ rom_init(rom_t *rom, wchar_t *fn, uint32_t addr, int sz, int mask, int off, uint } +int +rom_init_oddeven(rom_t *rom, wchar_t *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags) +{ + rom_log("rom_init(%08X, %08X, %08X, %08X, %08X, %08X, %08X)\n", rom, fn, addr, sz, mask, off, flags); + + /* Allocate a buffer for the image. */ + rom->rom = malloc(sz); + memset(rom->rom, 0xff, sz); + + /* Load the image file into the buffer. */ + if (! rom_load_linear_oddeven(fn, addr, sz, off, rom->rom)) { + /* Nope.. clean up. */ + free(rom->rom); + rom->rom = NULL; + return(-1); + } + + rom->sz = sz; + rom->mask = mask; + + mem_mapping_add(&rom->mapping, + addr, sz, + rom_read, rom_readw, rom_readl, + mem_write_null, mem_write_nullw, mem_write_nulll, + rom->rom, flags | MEM_MAPPING_ROM, rom); + + return(0); +} + + int rom_init_interleaved(rom_t *rom, wchar_t *fnl, wchar_t *fnh, uint32_t addr, int sz, int mask, int off, uint32_t flags) { diff --git a/src/pc.c b/src/pc.c index 1f25eba14..31586a4b3 100644 --- a/src/pc.c +++ b/src/pc.c @@ -1132,6 +1132,13 @@ set_screen_size(int x, int y) } +void +reset_screen_size(void) +{ + set_screen_size(unscaled_size_x, efscrnsz_y); +} + + void set_screen_size_natural(void) { diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index ca76ad23b..96a4e13a1 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -11,11 +11,13 @@ * * * - * Authors: TheCollector1995, - * Miran Grca, + * Authors: Miran Grca, + * tonioni, + * TheCollector1995, * - * Copyright 2016-2020 TheCollector1995. * Copyright 2016-2020 Miran Grca. + * Copyright 2020 tonioni. + * Copyright 2016-2020 TheCollector1995. */ #include #include @@ -89,7 +91,7 @@ #define CIRRUS_CURSOR_HIDDENPEL 0x02 #define CIRRUS_CURSOR_LARGE 0x04 /* 64x64 if set, 32x32 if clear */ -// sequencer 0x17 +/* sequencer 0x17 */ #define CIRRUS_BUSTYPE_VLBFAST 0x10 #define CIRRUS_BUSTYPE_PCI 0x20 #define CIRRUS_BUSTYPE_VLBSLOW 0x30 @@ -98,7 +100,7 @@ #define CIRRUS_MMIO_USE_PCIADDR 0x40 /* 0xb8000 if cleared. */ #define CIRRUS_MEMSIZEEXT_DOUBLE 0x80 -// control 0x0b +/* control 0x0b */ #define CIRRUS_BANKING_DUAL 0x01 #define CIRRUS_BANKING_GRANULARITY_16K 0x20 /* set:16k, clear:4k */ @@ -115,7 +117,7 @@ #define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 #define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 -// control 0x31 +/* control 0x31 */ #define CIRRUS_BLT_BUSY 0x01 #define CIRRUS_BLT_START 0x02 #define CIRRUS_BLT_RESET 0x04 @@ -124,7 +126,7 @@ #define CIRRUS_BLT_APERTURE2 0x40 #define CIRRUS_BLT_AUTOSTART 0x80 -// control 0x33 +/* control 0x33 */ #define CIRRUS_BLTMODEEXT_BACKGROUNDONLY 0x08 #define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 #define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 @@ -146,6 +148,7 @@ typedef struct gd54xx_t mem_mapping_t mmio_mapping; mem_mapping_t linear_mapping; mem_mapping_t aperture2_mapping; + mem_mapping_t vgablt_mapping; svga_t svga; @@ -187,11 +190,24 @@ typedef struct gd54xx_t int unlock_special; } blt; - int pci, vlb, mca; - int countminusone; + struct { + int mode; + uint16_t stride, r1sz, r1adjust, r2sz, + r2adjust, r2sdz, wvs, wve, + hzoom, vzoom; + uint8_t occlusion, colorkeycomparemask, + colorkeycompare; + int region1size, region2size, + colorkeymode; + uint32_t ck; + } overlay; + + int pci, vlb, mca, countminusone; + int vblank_irq, vportsync; uint8_t pci_regs[256]; - uint8_t int_line, unlocked; + uint8_t int_line, unlocked, status, extensions; + uint8_t crtcreg_mask; uint8_t fc; /* Feature Connector */ @@ -200,7 +216,7 @@ typedef struct gd54xx_t uint8_t pos_regs[8]; svga_t *mb_vga; - uint32_t lfb_base; + uint32_t lfb_base, vgablt_base; int mmio_vram_overlap; @@ -243,6 +259,266 @@ static void gd54xx_start_blit(uint32_t cpu_dat, uint32_t count, gd54xx_t *gd54xx, svga_t *svga); +#define CLAMP(x) do \ + { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } \ + while (0) + +#define DECODE_YCbCr() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 2; c++) \ + { \ + uint8_t y1, y2; \ + int8_t Cr, Cb; \ + int dR, dG, dB; \ + \ + y1 = src[0]; \ + Cr = src[1] - 0x80; \ + y2 = src[2]; \ + Cb = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359*Cr) >> 8; \ + dG = (88*Cb + 183*Cr) >> 8; \ + dB = (453*Cb) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write+1] = y2 + dR; \ + CLAMP(r[x_write+1]); \ + g[x_write+1] = y2 - dG; \ + CLAMP(g[x_write+1]); \ + b[x_write+1] = y2 + dB; \ + CLAMP(b[x_write+1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) + +/*Both YUV formats are untested*/ +#define DECODE_YUV211() \ + do \ + { \ + uint8_t y1, y2, y3, y4; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + y2 = (298 * (src[2] - 16)) >> 8; \ + V = src[3] - 0x80; \ + y3 = (298 * (src[4] - 16)) >> 8; \ + y4 = (298 * (src[5] - 16)) >> 8; \ + src += 6; \ + \ + dR = (309*V) >> 8; \ + dG = (100*U + 208*V) >> 8; \ + dB = (516*U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write+1] = y2 + dR; \ + CLAMP(r[x_write+1]); \ + g[x_write+1] = y2 - dG; \ + CLAMP(g[x_write+1]); \ + b[x_write+1] = y2 + dB; \ + CLAMP(b[x_write+1]); \ + \ + r[x_write+2] = y3 + dR; \ + CLAMP(r[x_write+2]); \ + g[x_write+2] = y3 - dG; \ + CLAMP(g[x_write+2]); \ + b[x_write+2] = y3 + dB; \ + CLAMP(b[x_write+2]); \ + \ + r[x_write+3] = y4 + dR; \ + CLAMP(r[x_write+3]); \ + g[x_write+3] = y4 - dG; \ + CLAMP(g[x_write+3]); \ + b[x_write+3] = y4 + dB; \ + CLAMP(b[x_write+3]); \ + \ + x_write = (x_write + 4) & 7; \ + } while (0) + +#define DECODE_YUV422() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 2; c++) \ + { \ + uint8_t y1, y2; \ + int8_t U, V; \ + int dR, dG, dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + V = src[2] - 0x80; \ + y2 = (298 * (src[3] - 16)) >> 8; \ + src += 4; \ + \ + dR = (309*V) >> 8; \ + dG = (100*U + 208*V) >> 8; \ + dB = (516*U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write+1] = y2 + dR; \ + CLAMP(r[x_write+1]); \ + g[x_write+1] = y2 - dG; \ + CLAMP(g[x_write+1]); \ + b[x_write+1] = y2 + dB; \ + CLAMP(b[x_write+1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ + } while (0) + +#define DECODE_RGB555() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 4; c++) \ + { \ + uint16_t dat; \ + \ + dat = *(uint16_t *)src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ + b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) + +#define DECODE_RGB565() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 4; c++) \ + { \ + uint16_t dat; \ + \ + dat = *(uint16_t *)src; \ + src += 2; \ + \ + r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ + g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ + b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) + +#define DECODE_CLUT() \ + do \ + { \ + int c; \ + \ + for (c = 0; c < 4; c++) \ + { \ + uint8_t dat; \ + \ + dat = *(uint8_t *)src; \ + src++; \ + \ + r[x_write + c] = svga->pallook[dat] >> 0; \ + g[x_write + c] = svga->pallook[dat] >> 8; \ + b[x_write + c] = svga->pallook[dat] >> 16; \ + } \ + x_write = (x_write + 4) & 7; \ + } while (0) + + + +#define OVERLAY_SAMPLE() \ + do \ + { \ + switch (gd54xx->overlay.mode) \ + { \ + case 0: \ + DECODE_YUV422(); \ + break; \ + case 2: \ + DECODE_CLUT(); \ + break; \ + case 3: \ + DECODE_YUV211(); \ + break; \ + case 4: \ + DECODE_RGB555(); \ + break; \ + case 5: \ + DECODE_RGB565(); \ + break; \ + } \ + } while (0) + + +static int +gd54xx_interrupt_enabled(gd54xx_t *gd54xx) +{ + return !gd54xx->pci || (gd54xx->svga.gdcreg[0x17] & 0x04); +} + + +static int +gd54xx_vga_vsync_enabled(gd54xx_t *gd54xx) +{ + if (!(gd54xx->svga.crtc[0x11] & 0x20) && (gd54xx->svga.crtc[0x11] & 0x10) && + gd54xx_interrupt_enabled(gd54xx)) + return 1; + return 0; +} + + +static void +gd54xx_update_irqs(gd54xx_t *gd54xx) +{ + if (!gd54xx->pci) + return; + + if ((gd54xx->vblank_irq > 0) && gd54xx_vga_vsync_enabled(gd54xx)) + pci_set_irq(gd54xx->card, PCI_INTA); + else + pci_clear_irq(gd54xx->card, PCI_INTA); +} + + +static void +gd54xx_vblank_start(svga_t *svga) +{ + gd54xx_t *gd54xx = (gd54xx_t*) svga->p; + if (gd54xx->vblank_irq >= 0) { + gd54xx->vblank_irq = 1; + gd54xx_update_irqs(gd54xx); + } +} + + /* Returns 1 if the card is a 5422+ */ static int gd54xx_is_5422(svga_t *svga) @@ -254,6 +530,92 @@ gd54xx_is_5422(svga_t *svga) } +static void +gd54xx_overlay_draw(svga_t *svga, int displine) +{ + gd54xx_t *gd54xx = (gd54xx_t *) svga->p; + int shift = (svga->crtc[0x27] >= CIRRUS_ID_CLGD5446) ? 2 : 0; + int h_acc = svga->overlay_latch.h_acc; + int r[8], g[8], b[8]; + int x_read = 4, x_write = 4; + int x; + uint32_t *p; + uint8_t *src = &svga->vram[(svga->overlay_latch.addr << shift) & svga->vram_mask]; + int bpp = svga->bpp; + int bytesperpix = (bpp + 7) / 8; + uint8_t *src2 = &svga->vram[(svga->ma - (svga->hdisp * bytesperpix)) & svga->vram_display_mask]; + int w = gd54xx->overlay.r2sdz; + int occl, ckval; + + if (gd54xx->overlay.mode == 2) + w *= 4; + else + w *= 2; + + p = &((uint32_t *)buffer32->line[displine])[gd54xx->overlay.region1size + svga->x_add]; + src2 += gd54xx->overlay.region1size * bytesperpix; + + OVERLAY_SAMPLE(); + + for (x = 0; (x < gd54xx->overlay.region2size) && + ((x + gd54xx->overlay.region1size) < svga->hdisp); x++) { + if (gd54xx->overlay.occlusion) { + occl = 1; + ckval = gd54xx->overlay.ck; + if (bytesperpix == 1) { + if (*src2 == ckval) + occl = 0; + } else if (bytesperpix == 2) { + if (*((uint16_t*)src2) == ckval) + occl = 0; + } else + occl = 0; + if (!occl) + *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); + src2 += bytesperpix; + } else + *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); + + h_acc += gd54xx->overlay.hzoom; + if (h_acc >= 256) { + if ((x_read ^ (x_read + 1)) & ~3) + OVERLAY_SAMPLE(); + x_read = (x_read + 1) & 7; + + h_acc -= 256; + } + } + + svga->overlay_latch.v_acc += gd54xx->overlay.vzoom; + if (svga->overlay_latch.v_acc >= 256) { + svga->overlay_latch.v_acc -= 256; + svga->overlay_latch.addr += svga->overlay.pitch << 1; + } +} + + +static void +gd54xx_update_overlay(gd54xx_t *gd54xx) +{ + svga_t *svga = &gd54xx->svga; + int bpp = svga->bpp; + + svga->overlay.ysize = gd54xx->overlay.wve - gd54xx->overlay.wvs + 1; + gd54xx->overlay.region1size = 32 * gd54xx->overlay.r1sz / bpp + (gd54xx->overlay.r1adjust * 8 / bpp); + gd54xx->overlay.region2size = 32 * gd54xx->overlay.r2sz / bpp + (gd54xx->overlay.r2adjust * 8 / bpp); + + gd54xx->overlay.occlusion = (svga->crtc[0x3e] & 0x80) != 0 && svga->bpp <= 16; + + /* Mask and chroma key ignored. */ + if (gd54xx->overlay.colorkeymode == 0) + gd54xx->overlay.ck = gd54xx->overlay.colorkeycompare; + else if (gd54xx->overlay.colorkeymode == 1) + gd54xx->overlay.ck = gd54xx->overlay.colorkeycompare | (gd54xx->overlay.colorkeycomparemask << 8); + else + gd54xx->overlay.occlusion = 0; +} + + /* Returns 1 if the card supports the 8-bpp/16-bpp transparency color or mask. */ static int gd54xx_has_transp(svga_t *svga, int mask) @@ -538,6 +900,15 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) gd54xx_recalc_banking(gd54xx); break; + case 0x0c: + gd54xx->overlay.colorkeycompare = val; + gd54xx_update_overlay(gd54xx); + break; + case 0x0d: + gd54xx->overlay.colorkeycomparemask = val; + gd54xx_update_overlay(gd54xx); + break; + case 0x10: gd543x_mmio_write(0xb8001, val, gd54xx); break; @@ -640,7 +1011,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) } return; case 0x3d4: - svga->crtcreg = val & 0x3f; + svga->crtcreg = val & gd54xx->crtcreg_mask; return; case 0x3d5: if (((svga->crtcreg == 0x19) || (svga->crtcreg == 0x1a) || @@ -655,7 +1026,104 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; + if (svga->crtcreg == 0x11) { + if (!(val & 0x10)) { + if (gd54xx->vblank_irq > 0) + gd54xx->vblank_irq = -1; + } else if (gd54xx->vblank_irq < 0) + gd54xx->vblank_irq = 0; + gd54xx_update_irqs(gd54xx); + if ((val & ~0x30) == (old & ~0x30)) + old = val; + } + if (old != val) { + /* Overlay registers */ + switch (svga->crtcreg) { + case 0x1d: + if (((old >> 3) & 7) != ((val >> 3) & 7)) { + gd54xx->overlay.colorkeymode = (val >> 3) & 7; + gd54xx_update_overlay(gd54xx); + } + break; + case 0x31: + gd54xx->overlay.hzoom = val == 0 ? 256 : val; + gd54xx_update_overlay(gd54xx); + break; + case 0x32: + gd54xx->overlay.vzoom = val == 0 ? 256 : val; + gd54xx_update_overlay(gd54xx); + break; + case 0x33: + gd54xx->overlay.r1sz &= ~0xff; + gd54xx->overlay.r1sz |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x34: + gd54xx->overlay.r2sz &= ~0xff; + gd54xx->overlay.r2sz |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x35: + gd54xx->overlay.r2sdz &= ~0xff; + gd54xx->overlay.r2sdz |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x36: + gd54xx->overlay.r1sz &= 0xff; + gd54xx->overlay.r1sz |= (val << 8) & 0x300; + gd54xx->overlay.r2sz &= 0xff; + gd54xx->overlay.r2sz |= (val << 6) & 0x300; + gd54xx->overlay.r2sdz &= 0xff; + gd54xx->overlay.r2sdz |= (val << 4) & 0x300; + gd54xx_update_overlay(gd54xx); + break; + case 0x37: + gd54xx->overlay.wvs &= ~0xff; + gd54xx->overlay.wvs |= val; + svga->overlay.y = gd54xx->overlay.wvs; + break; + case 0x38: + gd54xx->overlay.wve &= ~0xff; + gd54xx->overlay.wve |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x39: + gd54xx->overlay.wvs &= 0xff; + gd54xx->overlay.wvs |= (val << 8) & 0x300; + gd54xx->overlay.wve &= 0xff; + gd54xx->overlay.wve |= (val << 6) & 0x300; + gd54xx_update_overlay(gd54xx); + break; + case 0x3a: + svga->overlay.addr &= ~0xff; + svga->overlay.addr |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x3b: + svga->overlay.addr &= ~0xff00; + svga->overlay.addr |= val << 8; + gd54xx_update_overlay(gd54xx); + break; + case 0x3c: + svga->overlay.addr &= ~0x0f0000; + svga->overlay.addr |= (val << 16) & 0x0f0000; + svga->overlay.pitch &= ~0x100; + svga->overlay.pitch |= (val & 0x20) << 3; + gd54xx_update_overlay(gd54xx); + break; + case 0x3d: + svga->overlay.pitch &= ~0xff; + svga->overlay.pitch |= val; + gd54xx_update_overlay(gd54xx); + break; + case 0x3e: + gd54xx->overlay.mode = (val >> 1) & 7; + svga->overlay.ena = (val & 1) != 0; + gd54xx_update_overlay(gd54xx); + break; + } + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { svga->fullchange = changeframecount; svga_recalctimings(svga); @@ -679,6 +1147,11 @@ gd54xx_in(uint16_t addr, void *p) addr ^= 0x60; switch (addr) { + case 0x3c2: + ret = svga_in(addr, svga); + ret |= gd54xx->vblank_irq > 0 ? 0x80 : 0x00; + break; + case 0x3c4: if (svga->seqregs[6] == 0x12) { ret = svga->seqaddr; @@ -911,6 +1384,12 @@ gd54xx_in(uint16_t addr, void *p) case 0x39: ret = gd543x_mmio_read(0xb8021, gd54xx); break; + + case 0x3f: + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5446) + gd54xx->vportsync = !gd54xx->vportsync; + ret = gd54xx->vportsync ? 0x80 : 0x00; + break; } } else { if ((svga->gdcaddr < 2) && !gd54xx->unlocked) @@ -1056,7 +1535,9 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) } } else if (gd54xx->pci) { base = gd54xx->lfb_base; - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) + /* if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) + size = 32 * 1024 * 1024; + else */ if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) size = 16 * 1024 * 1024; else size = 4 * 1024 * 1024; @@ -1080,9 +1561,12 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) && (gd54xx->blt.status & CIRRUS_BLT_APERTURE2) && ((gd54xx->blt.mode & (CIRRUS_BLTMODE_COLOREXPAND | CIRRUS_BLTMODE_MEMSYSSRC)) == - (CIRRUS_BLTMODE_COLOREXPAND | CIRRUS_BLTMODE_MEMSYSSRC))) - mem_mapping_set_addr(&gd54xx->aperture2_mapping, 0xbc000, 0x04000); - else + (CIRRUS_BLTMODE_COLOREXPAND | CIRRUS_BLTMODE_MEMSYSSRC))) { + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) + mem_mapping_set_addr(&gd54xx->aperture2_mapping, gd54xx->lfb_base + (16777216), 16777216); + else + mem_mapping_set_addr(&gd54xx->aperture2_mapping, 0xbc000, 0x04000); + } else mem_mapping_disable(&gd54xx->aperture2_mapping); } } @@ -1093,15 +1577,19 @@ gd54xx_recalctimings(svga_t *svga) { gd54xx_t *gd54xx = (gd54xx_t *)svga->p; uint8_t clocksel, rdmask; + uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; svga->rowoffset = (svga->crtc[0x13]) | ((svga->crtc[0x1b] & 0x10) << 4); svga->interlace = (svga->crtc[0x1a] & 0x01); svga->map8 = svga->pallook; - if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) - svga->render = svga_render_8bpp_highres; - else if (svga->gdcreg[5] & 0x40) + if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) { + if (linedbl) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + } else if (svga->gdcreg[5] & 0x40) svga->render = svga_render_8bpp_lowres; svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15); @@ -1118,39 +1606,61 @@ gd54xx_recalctimings(svga_t *svga) switch (gd54xx->ramdac.ctrl & rdmask) { case 0: svga->bpp = 15; - if (gd54xx->ramdac.ctrl & 0x10) - svga->render = svga_render_15bpp_mix_highres; - else - svga->render = svga_render_15bpp_highres; + if (linedbl) { + if (gd54xx->ramdac.ctrl & 0x10) + svga->render = svga_render_15bpp_mix_lowres; + else + svga->render = svga_render_15bpp_lowres; + } else { + if (gd54xx->ramdac.ctrl & 0x10) + svga->render = svga_render_15bpp_mix_highres; + else + svga->render = svga_render_15bpp_highres; + } break; case 1: svga->bpp = 16; - svga->render = svga_render_16bpp_highres; + if (linedbl) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; break; case 5: if (gd54xx_is_5434(svga) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32)) { svga->bpp = 32; - svga->render = svga_render_32bpp_highres; + if (linedbl) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) svga->rowoffset *= 2; } else { svga->bpp = 24; - svga->render = svga_render_24bpp_highres; + if (linedbl) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; } break; case 8: svga->bpp = 8; svga->map8 = video_8togs; - svga->render = svga_render_8bpp_highres; + if (linedbl) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; break; case 9: svga->bpp = 8; svga->map8 = video_8to32; - svga->render = svga_render_8bpp_highres; + if (linedbl) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; break; case 0xf: @@ -1158,41 +1668,63 @@ gd54xx_recalctimings(svga_t *svga) case CIRRUS_SR7_BPP_32: if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430) { svga->bpp = 32; - svga->render = svga_render_32bpp_highres; + if (linedbl) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; svga->rowoffset *= 2; } break; case CIRRUS_SR7_BPP_24: svga->bpp = 24; - svga->render = svga_render_24bpp_highres; + if (linedbl) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; break; case CIRRUS_SR7_BPP_16: if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5428) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5426)) { svga->bpp = 16; - svga->render = svga_render_16bpp_highres; + if (linedbl) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; } break; case CIRRUS_SR7_BPP_16_DOUBLEVCLK: svga->bpp = 16; - svga->render = svga_render_16bpp_highres; + if (linedbl) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; break; case CIRRUS_SR7_BPP_8: svga->bpp = 8; - svga->render = svga_render_8bpp_highres; + if (linedbl) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; break; } break; } } else { svga->bpp = 15; - if (gd54xx->ramdac.ctrl & 0x10) - svga->render = svga_render_15bpp_mix_highres; - else - svga->render = svga_render_15bpp_highres; + if (linedbl) { + if (gd54xx->ramdac.ctrl & 0x10) + svga->render = svga_render_15bpp_mix_lowres; + else + svga->render = svga_render_15bpp_lowres; + } else { + if (gd54xx->ramdac.ctrl & 0x10) + svga->render = svga_render_15bpp_mix_highres; + else + svga->render = svga_render_15bpp_highres; + } } } @@ -1233,16 +1765,19 @@ void gd54xx_hwcursor_draw(svga_t *svga, int displine) int pitch = (svga->hwcursor.xsize == 64) ? 16 : 4; uint32_t bgcol = gd54xx->extpallook[0x00]; uint32_t fgcol = gd54xx->extpallook[0x0f]; + uint8_t linedbl = svga->dispend * 9 / 10 >= svga->hdisp; + + offset <<= linedbl; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += pitch; for (x = 0; x < svga->hwcursor.xsize; x += 8) { - dat[0] = svga->vram[svga->hwcursor_latch.addr]; + dat[0] = svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask]; if (svga->hwcursor.xsize == 64) - dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x08]; + dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x08) & svga->vram_display_mask]; else - dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80]; + dat[1] = svga->vram[(svga->hwcursor_latch.addr + 0x80) & svga->vram_display_mask]; for (xx = 0; xx < 8; xx++) { b0 = (dat[0] >> (7 - xx)) & 1; b1 = (dat[1] >> (7 - xx)) & 1; @@ -2451,6 +2986,98 @@ gd543x_mmio_readl(uint32_t addr, void *p) } +static void +gd5480_vgablt_write(uint32_t addr, uint8_t val, void *p) +{ + addr &= 0x00000fff; + + if ((addr >= 0x00000100) && (addr < 0x00000200)) + gd543x_mmio_writeb((addr & 0x000000ff) | 0x000b8000, val, p); + else if (addr < 0x00000100) + gd54xx_out(0x03c0 + addr, val, p); +} + + +static void +gd5480_vgablt_writew(uint32_t addr, uint16_t val, void *p) +{ + addr &= 0x00000fff; + + if ((addr >= 0x00000100) && (addr < 0x00000200)) + gd543x_mmio_writew((addr & 0x000000ff) | 0x000b8000, val, p); + else if (addr < 0x00000100) { + gd5480_vgablt_write(addr, val & 0xff, p); + gd5480_vgablt_write(addr + 1, val >> 8, p); + } +} + + +static void +gd5480_vgablt_writel(uint32_t addr, uint32_t val, void *p) +{ + addr &= 0x00000fff; + + if ((addr >= 0x00000100) && (addr < 0x00000200)) + gd543x_mmio_writel((addr & 0x000000ff) | 0x000b8000, val, p); + else if (addr < 0x00000100) { + gd5480_vgablt_writew(addr, val & 0xffff, p); + gd5480_vgablt_writew(addr + 2, val >> 16, p); + } +} + + +static uint8_t +gd5480_vgablt_read(uint32_t addr, void *p) +{ + uint8_t ret = 0xff; + + addr &= 0x00000fff; + + if ((addr >= 0x00000100) && (addr < 0x00000200)) + ret = gd543x_mmio_read((addr & 0x000000ff) | 0x000b8000, p); + else if (addr < 0x00000100) + ret = gd54xx_in(0x03c0 + addr, p); + + return ret; +} + + +static uint16_t +gd5480_vgablt_readw(uint32_t addr, void *p) +{ + uint16_t ret = 0xffff; + + addr &= 0x00000fff; + + if ((addr >= 0x00000100) && (addr < 0x00000200)) + ret = gd543x_mmio_readw((addr & 0x000000ff) | 0x000b8000, p); + else if (addr < 0x00000100) { + ret = gd5480_vgablt_read(addr, p); + ret |= (gd5480_vgablt_read(addr + 1, p) << 8); + } + + return ret; +} + + +static uint32_t +gd5480_vgablt_readl(uint32_t addr, void *p) +{ + uint32_t ret = 0xffffffff; + + addr &= 0x00000fff; + + if ((addr >= 0x00000100) && (addr < 0x00000200)) + ret = gd543x_mmio_readl((addr & 0x000000ff) | 0x000b8000, p); + else if (addr < 0x00000100) { + ret = gd5480_vgablt_readw(addr, p); + ret |= (gd5480_vgablt_readw(addr + 2, p) << 16); + } + + return ret; +} + + static uint8_t gd54xx_color_expand(gd54xx_t *gd54xx, int mask, int shift) { @@ -2947,6 +3574,21 @@ cl_pci_read(int func, int addr, void *p) break; case 0x13: ret = gd54xx->lfb_base >> 24; + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) + ret = 0xfe; + break; + + case 0x14: + ret = 0x00; /*PCI VGA/BitBLT Register Base Address*/ + break; + case 0x15: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 8) & 0xf0) : 0x00; + break; + case 0x16: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 16) & 0xff) : 0x00; + break; + case 0x17: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 24) & 0xff) : 0x00; break; case 0x30: @@ -2978,6 +3620,8 @@ static void cl_pci_write(int func, int addr, uint8_t val, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; + svga_t *svga = &gd54xx->svga; + uint32_t byte; if ((addr >= 0x30) && (addr <= 0x33) && (!gd54xx->has_bios)) return; @@ -2985,17 +3629,37 @@ cl_pci_write(int func, int addr, uint8_t val, void *p) switch (addr) { case PCI_REG_COMMAND: gd54xx->pci_regs[PCI_REG_COMMAND] = val & 0x23; + mem_mapping_disable(&gd54xx->vgablt_mapping); io_removehandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); if (val & PCI_COMMAND_IO) io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); + if ((val & PCI_COMMAND_MEM) && (gd54xx->vgablt_base != 0x00000000) && (gd54xx->vgablt_base < 0xfff00000)) + mem_mapping_set_addr(&gd54xx->vgablt_mapping, gd54xx->vgablt_base, 0x1000); gd543x_recalc_mapping(gd54xx); break; - case 0x13: + case 0x13: + /* 5480, like 5446 rev. B, has a 32 MB aperture, with the second set used for + BitBLT transfers. */ + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) + val &= 0xfe; gd54xx->lfb_base = val << 24; gd543x_recalc_mapping(gd54xx); break; + case 0x15: case 0x16: case 0x17: + if (svga->crtc[0x27] != CIRRUS_ID_CLGD5480) + return; + byte = (addr & 3) << 3; + gd54xx->vgablt_base &= ~(0xff << byte); + if (addr == 0x15) + val &= 0xf0; + gd54xx->vgablt_base |= (val << byte); + mem_mapping_disable(&gd54xx->vgablt_mapping); + if ((gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM) && (gd54xx->vgablt_base != 0x00000000) && (gd54xx->vgablt_base < 0xfff00000)) + mem_mapping_set_addr(&gd54xx->vgablt_mapping, gd54xx->vgablt_base, 0x1000); + break; + case 0x30: case 0x32: case 0x33: gd54xx->pci_regs[addr] = val; if (gd54xx->pci_regs[0x30] & 0x01) { @@ -3173,7 +3837,6 @@ static void if (romfn) rom_init(&gd54xx->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (info->flags & DEVICE_ISA) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_isa); else if (info->flags & DEVICE_PCI) @@ -3181,9 +3844,16 @@ static void else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_gd54xx_vlb); - svga_init(info, &gd54xx->svga, gd54xx, gd54xx->vram_size, - gd54xx_recalctimings, gd54xx_in, gd54xx_out, - gd54xx_hwcursor_draw, NULL); + if (id >= CIRRUS_ID_CLGD5426) { + svga_init(info, &gd54xx->svga, gd54xx, gd54xx->vram_size, + gd54xx_recalctimings, gd54xx_in, gd54xx_out, + gd54xx_hwcursor_draw, gd54xx_overlay_draw); + } else { + svga_init(info, &gd54xx->svga, gd54xx, gd54xx->vram_size, + gd54xx_recalctimings, gd54xx_in, gd54xx_out, + gd54xx_hwcursor_draw, NULL); + } + svga->vblank_start = gd54xx_vblank_start; svga->ven_write = gd54xx_write_modes45; if (vram <= 1) svga->decode_mask = gd54xx->vram_mask; @@ -3202,6 +3872,10 @@ static void gd5436_aperture2_readb, gd5436_aperture2_readw, gd5436_aperture2_readl, gd5436_aperture2_writeb, gd5436_aperture2_writew, gd5436_aperture2_writel, NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_add(&gd54xx->vgablt_mapping, 0, 0, + gd5480_vgablt_read, gd5480_vgablt_readw, gd5480_vgablt_readl, + gd5480_vgablt_write, gd5480_vgablt_writew, gd5480_vgablt_writel, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); } else { mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, NULL, gd54xx_write, gd54xx_writew, NULL); mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, @@ -3216,11 +3890,16 @@ static void gd5436_aperture2_readb, gd5436_aperture2_readw, NULL, gd5436_aperture2_writeb, gd5436_aperture2_writew, NULL, NULL, MEM_MAPPING_EXTERNAL, gd54xx); + mem_mapping_add(&gd54xx->vgablt_mapping, 0, 0, + gd5480_vgablt_read, gd5480_vgablt_readw, NULL, + gd5480_vgablt_write, gd5480_vgablt_writew, NULL, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); } mem_mapping_set_p(&svga->mapping, gd54xx); mem_mapping_disable(&gd54xx->mmio_mapping); mem_mapping_disable(&gd54xx->linear_mapping); mem_mapping_disable(&gd54xx->aperture2_mapping); + mem_mapping_disable(&gd54xx->vgablt_mapping); io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); @@ -3274,6 +3953,13 @@ static void gd54xx->ddc = ddc_init(i2c_gpio_get_bus(gd54xx->i2c)); } + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5446) + gd54xx->crtcreg_mask = 0x7f; + else + gd54xx->crtcreg_mask = 0x3f; + + gd54xx->overlay.colorkeycompare = 0xff; + return gd54xx; } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index efe663d8c..0e1511af4 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -1063,8 +1063,6 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) switch (svga->writemode) { case 0: val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); - // if (svga->gdcreg[3] & 7) - // val = svga_rotate[svga->gdcreg[3] & 7][val]; if ((svga->gdcreg[8] == 0xff) && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { for (i = 0; i < count; i++) { if ((svga->adv_flags & FLAG_EXT_WRITE) && (svga->adv_flags & FLAG_ADDR_BY8)) { @@ -1115,8 +1113,6 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) break; case 3: val = ((val >> (svga->gdcreg[3] & 7)) | (val << (8 - (svga->gdcreg[3] & 7)))); - // if (svga->gdcreg[3] & 7) - // val = svga_rotate[svga->gdcreg[3] & 7][val]; wm = svga->gdcreg[8]; svga->gdcreg[8] &= val; diff --git a/src/win/win.c b/src/win/win.c index 0d465f2f3..50c87d015 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -86,23 +86,14 @@ static const struct { void (*resize)(int x, int y); int (*pause)(void); void (*enable)(int enable); -} vid_apis[2][RENDERERS_NUM] = { - { - { "SDL_Software", 1, (int(*)(void*))sdl_inits, sdl_close, NULL, sdl_pause, sdl_enable }, - { "SDL_Hardware", 1, (int(*)(void*))sdl_inith, sdl_close, NULL, sdl_pause, sdl_enable }, - { "SDL_OpenGL", 1, (int(*)(void*))sdl_initho, sdl_close, NULL, sdl_pause, sdl_enable } + void (*set_fs)(int fs); +} vid_apis[RENDERERS_NUM] = { + { "SDL_Software", 1, (int(*)(void*))sdl_inits, sdl_close, NULL, sdl_pause, sdl_enable, sdl_set_fs }, + { "SDL_Hardware", 1, (int(*)(void*))sdl_inith, sdl_close, NULL, sdl_pause, sdl_enable, sdl_set_fs }, + { "SDL_OpenGL", 1, (int(*)(void*))sdl_initho, sdl_close, NULL, sdl_pause, sdl_enable, sdl_set_fs } #ifdef USE_VNC - ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause, NULL } + ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause, NULL, NULL } #endif - }, - { - { "SDL_Software", 1, (int(*)(void*))sdl_inits_fs, sdl_close, sdl_resize, sdl_pause, sdl_enable }, - { "SDL_Hardware", 1, (int(*)(void*))sdl_inith_fs, sdl_close, sdl_resize, sdl_pause, sdl_enable }, - { "SDL_OpenGL", 1, (int(*)(void*))sdl_initho_fs, sdl_close, sdl_resize, sdl_pause, sdl_enable } -#ifdef USE_VNC - ,{ "VNC", 0, vnc_init, vnc_close, vnc_resize, vnc_pause, NULL } -#endif - }, }; @@ -681,8 +672,8 @@ plat_vidapi(char *name) if (!strcasecmp(name, "ddraw") || !strcasecmp(name, "sdl")) return(1); for (i = 0; i < RENDERERS_NUM; i++) { - if (vid_apis[0][i].name && - !strcasecmp(vid_apis[0][i].name, name)) return(i); + if (vid_apis[i].name && + !strcasecmp(vid_apis[i].name, name)) return(i); } /* Default value. */ @@ -730,16 +721,16 @@ plat_setvid(int api) video_wait_for_blit(); /* Close the (old) API. */ - vid_apis[0][vid_api].close(); + vid_apis[vid_api].close(); vid_api = api; - if (vid_apis[0][vid_api].local) + if (vid_apis[vid_api].local) ShowWindow(hwndRender, SW_SHOW); else ShowWindow(hwndRender, SW_HIDE); /* Initialize the (new) API. */ - i = vid_apis[0][vid_api].init((void *)hwndRender); + i = vid_apis[vid_api].init((void *)hwndRender); endblit(); if (! i) return(0); @@ -755,11 +746,11 @@ plat_setvid(int api) void plat_vidsize(int x, int y) { - if (!vid_api_inited || !vid_apis[video_fullscreen][vid_api].resize) return; + if (!vid_api_inited || !vid_apis[vid_api].resize) return; startblit(); video_wait_for_blit(); - vid_apis[video_fullscreen][vid_api].resize(x, y); + vid_apis[vid_api].resize(x, y); endblit(); } @@ -769,66 +760,61 @@ plat_vidapi_enable(int enable) { int i = 1; - if (!vid_api_inited || !vid_apis[video_fullscreen][vid_api].enable) return; + if (!vid_api_inited || !vid_apis[vid_api].enable) + return; - startblit(); video_wait_for_blit(); + vid_apis[vid_api].enable(enable != 0); - vid_apis[video_fullscreen][vid_api].enable(enable & 1); + if (! i) + return; - endblit(); - - if (! i) return; - - if (enable) + if (enable) device_force_redraw(); } + int get_vidpause(void) { - return(vid_apis[video_fullscreen][vid_api].pause()); + return(vid_apis[vid_api].pause()); } void plat_setfullscreen(int on) { - HWND *hw; - - /* Want off and already off? */ - if (!on && !video_fullscreen) return; - - /* Want on and already on? */ - if (on && video_fullscreen) return; + /* Are we changing from the same state to the same state? */ + if ((!!on) == (!!video_fullscreen)) + return; if (on && video_fullscreen_first) { + video_fullscreen |= 2; if (ui_msgbox_header(MBX_INFO | MBX_DONTASK, (wchar_t *) IDS_2134, (wchar_t *) IDS_2052) == 10) { video_fullscreen_first = 0; config_save(); } + video_fullscreen &= 1; } /* OK, claim the video. */ - startblit(); video_wait_for_blit(); - - plat_vidapi_enable(0); - win_mouse_close(); /* Close the current mode, and open the new one. */ - vid_apis[video_fullscreen][vid_api].close(); - video_fullscreen = on; - hw = (video_fullscreen) ? &hwndMain : &hwndRender; - vid_apis[video_fullscreen][vid_api].init((void *) *hw); + video_fullscreen = on | 2; + if (vid_apis[vid_api].set_fs) + vid_apis[vid_api].set_fs(on); + if (!on) + plat_resize(scrnsz_x, scrnsz_y); + video_fullscreen &= 1; + video_force_resize_set(1); + if (!on) + doresize = 1; win_mouse_init(); - plat_vidapi_enable(1); - /* Release video and make it redraw the screen. */ - endblit(); device_force_redraw(); /* Send a CTRL break code so CTRL does not get stuck. */ @@ -837,6 +823,10 @@ plat_setfullscreen(int on) /* Finally, handle the host's mouse cursor. */ /* win_log("%s full screen, %s cursor\n", on ? "enter" : "leave", on ? "hide" : "show"); */ show_cursor(video_fullscreen ? 0 : -1); + + /* This is needed for OpenGL. */ + plat_vidapi_enable(0); + plat_vidapi_enable(1); } diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index db12f2cc8..7e29d6381 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -82,7 +82,6 @@ static SDL_Window *sdl_win = NULL; static SDL_Renderer *sdl_render = NULL; static SDL_Texture *sdl_tex = NULL; static HWND sdl_parent_hwnd = NULL; -static HWND sdl_hwnd = NULL; static int sdl_w, sdl_h; static int sdl_fs, sdl_flags = -1; static int cur_w, cur_h; @@ -181,6 +180,7 @@ sdl_stretch(int *w, int *h, int *x, int *y) switch (video_fullscreen_scale) { case FULLSCR_SCALE_FULL: + default: *w = sdl_w; *h = sdl_h; *x = 0; @@ -225,8 +225,6 @@ sdl_stretch(int *w, int *h, int *x, int *y) *y = (int) dy; break; } - - sdl_reinit_texture(); } @@ -236,17 +234,7 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h) SDL_Rect r_src; int ret; - if (!sdl_enabled) { - video_blit_complete(); - return; - } - - if ((y1 == y2) || (h <= 0)) { - video_blit_complete(); - return; - } - - if (render_buffer == NULL) { + if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL)) { video_blit_complete(); return; } @@ -260,13 +248,6 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h) SDL_UpdateTexture(sdl_tex, &r_src, &(render_buffer->dat)[y1 * w], w * 4); video_blit_complete(); - if (sdl_fs) { - sdl_log("sdl_blit(%i, %i, %i, %i, %i, %i) (%i, %i)\n", x, y, y1, y2, w, h, unscaled_size_x, efscrnsz_y); - if (w == unscaled_size_x) - sdl_resize(w, h); - sdl_log("(%08X, %08X, %08X)\n", sdl_win, sdl_render, sdl_tex); - } - SDL_RenderClear(sdl_render); r_src.x = 0; @@ -279,11 +260,31 @@ sdl_blit(int x, int y, int y1, int y2, int w, int h) sdl_log("SDL: unable to copy texture to renderer (%s)\n", sdl_GetError()); SDL_RenderPresent(sdl_render); - SDL_UnlockMutex(sdl_mutex); } +static void +sdl_destroy_window(void) +{ + if (sdl_win != NULL) { + SDL_DestroyWindow(sdl_win); + sdl_win = NULL; + } +} + + +static void +sdl_destroy_texture(void) +{ + /* SDL_DestroyRenderer also automatically destroys all associated textures. */ + if (sdl_render != NULL) { + SDL_DestroyRenderer(sdl_render); + sdl_render = NULL; + } +} + + void sdl_close(void) { @@ -300,32 +301,10 @@ sdl_close(void) sdl_mutex = NULL; } - if (sdl_tex != NULL) { - SDL_DestroyTexture(sdl_tex); - sdl_tex = NULL; - } - - if (sdl_render != NULL) { - SDL_DestroyRenderer(sdl_render); - sdl_render = NULL; - } - - if (sdl_win != NULL) { - SDL_DestroyWindow(sdl_win); - sdl_win = NULL; - } - - if (sdl_hwnd != NULL) { - plat_set_input(hwndMain); - - ShowWindow(hwndRender, TRUE); - - SetFocus(hwndMain); - - if (sdl_fs) - DestroyWindow(sdl_hwnd); - sdl_hwnd = NULL; - } + sdl_destroy_texture(); + sdl_destroy_window(); + ImmAssociateContext(hwndMain, NULL); + SetFocus(hwndMain); if (sdl_parent_hwnd != NULL) { DestroyWindow(sdl_parent_hwnd); @@ -334,7 +313,6 @@ sdl_close(void) /* Quit. */ SDL_Quit(); - sdl_flags = -1; } @@ -359,13 +337,87 @@ sdl_select_best_hw_driver(void) } +static void +sdl_reinit_texture(void) +{ + if (sdl_flags == -1) + return; + + sdl_destroy_texture(); + + if (sdl_flags & RENDERER_HARDWARE) { + sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2"); + } else + sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); + + sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, 2048, 2048); +} + + +void +sdl_set_fs(int fs) +{ + int w = 0, h = 0, x = 0, y = 0; + RECT rect; + + SDL_LockMutex(sdl_mutex); + sdl_enabled = 0; + sdl_destroy_texture(); + + if (fs) { + ShowWindow(sdl_parent_hwnd, TRUE); + SetParent(hwndRender, sdl_parent_hwnd); + ShowWindow(hwndRender, TRUE); + MoveWindow(sdl_parent_hwnd, 0, 0, sdl_w, sdl_h, TRUE); + + /* Show the window, make it topmost, and give it focus. */ + w = unscaled_size_x; + h = efscrnsz_y; + sdl_stretch(&w, &h, &x, &y); + MoveWindow(hwndRender, x, y, w, h, TRUE); + ImmAssociateContext(sdl_parent_hwnd, NULL); + SetFocus(sdl_parent_hwnd); + + /* Redirect RawInput to this new window. */ + old_capture = mouse_capture; + GetWindowRect(hwndRender, &rect); + ClipCursor(&rect); + mouse_capture = 1; + } else { + SetParent(hwndRender, hwndMain); + ShowWindow(sdl_parent_hwnd, FALSE); + ShowWindow(hwndRender, TRUE); + ImmAssociateContext(hwndMain, NULL); + SetFocus(hwndMain); + mouse_capture = old_capture; + + if (mouse_capture) { + GetWindowRect(hwndRender, &rect); + ClipCursor(&rect); + } else + ClipCursor(&oldclip); + } + + sdl_fs = fs; + + if (fs) + sdl_flags |= RENDERER_FULL_SCREEN; + else + sdl_flags &= ~RENDERER_FULL_SCREEN; + + sdl_reinit_texture(); + sdl_enabled = 1; + SDL_UnlockMutex(sdl_mutex); +} + + static int sdl_init_common(int flags) { wchar_t temp[128]; SDL_version ver; - int w = 0, h = 0, x = 0, y = 0; - RECT rect; sdl_log("SDL: init (fs=%d)\n", fs); @@ -386,111 +438,24 @@ sdl_init_common(int flags) sdl_select_best_hw_driver(); } - if (flags & RENDERER_FULL_SCREEN) { - /* Get the size of the (current) desktop. */ - sdl_w = GetSystemMetrics(SM_CXSCREEN); - sdl_h = GetSystemMetrics(SM_CYSCREEN); + /* Get the size of the (current) desktop. */ + sdl_w = GetSystemMetrics(SM_CXSCREEN); + sdl_h = GetSystemMetrics(SM_CYSCREEN); - /* Create the desktop-covering window. */ - _swprintf(temp, L"%s v%s", EMU_NAME_W, EMU_VERSION_W); - sdl_parent_hwnd = CreateWindow(SUB_CLASS_NAME, - temp, - WS_POPUP, - 0, 0, sdl_w, sdl_h, - HWND_DESKTOP, - NULL, - hinstance, - NULL); + /* Create the desktop-covering window. */ + _swprintf(temp, L"%s v%s", EMU_NAME_W, EMU_VERSION_W); + sdl_parent_hwnd = CreateWindow(SDL_CLASS_NAME, temp, WS_POPUP, 0, 0, sdl_w, sdl_h, + HWND_DESKTOP, NULL, hinstance, NULL); + ShowWindow(sdl_parent_hwnd, FALSE); - SetWindowPos(sdl_parent_hwnd, HWND_TOPMOST, - 0, 0, sdl_w, sdl_h, SWP_SHOWWINDOW); + sdl_flags = flags; - /* Create the actual rendering window. */ - _swprintf(temp, L"%s v%s", EMU_NAME_W, EMU_VERSION_W); - sdl_hwnd = CreateWindow(SUB_CLASS_NAME, - temp, - WS_POPUP, - 0, 0, sdl_w, sdl_h, - sdl_parent_hwnd, - NULL, - hinstance, - NULL); - sdl_log("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd); - - /* Redirect RawInput to this new window. */ - plat_set_input(sdl_hwnd); - - SetFocus(sdl_hwnd); - - /* Show the window, make it topmost, and give it focus. */ - w = unscaled_size_x; - h = efscrnsz_y; - sdl_stretch(&w, &h, &x, &y); - SetWindowPos(sdl_hwnd, sdl_parent_hwnd, - x, y, w, h, SWP_SHOWWINDOW); - - /* Now create the SDL window from that. */ - sdl_win = SDL_CreateWindowFrom((void *)sdl_hwnd); - - old_capture = mouse_capture; - - GetWindowRect(sdl_hwnd, &rect); - - ClipCursor(&rect); - - mouse_capture = 1; - } else { - /* Create the SDL window from the render window. */ - sdl_win = SDL_CreateWindowFrom((void *)hwndRender); - - mouse_capture = old_capture; - - if (mouse_capture) { - GetWindowRect(hwndRender, &rect); - - ClipCursor(&rect); - } else { - ClipCursor(&oldclip); - } - } if (sdl_win == NULL) { sdl_log("SDL: unable to CreateWindowFrom (%s)\n", SDL_GetError()); - sdl_close(); - return(0); } - /* - * TODO: - * SDL_RENDERER_SOFTWARE, because SDL tries to do funky stuff - * otherwise (it turns off Win7 Aero and it looks like it's - * trying to switch to fullscreen even though the window is - * not a fullscreen window?) - */ - if (flags & RENDERER_HARDWARE) { - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2"); - } else - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); - - if (sdl_render == NULL) { - sdl_log("SDL: unable to create renderer (%s)\n", SDL_GetError()); - sdl_close(); - return(0); - } - - /* - * TODO: - * Actually the source is (apparently) XRGB8888, but the alpha - * channel seems to be set to 255 everywhere, so ARGB8888 works - * just as well. - */ - sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, 2048, 2048); - if (sdl_tex == NULL) { - sdl_log("SDL: unable to create texture (%s)\n", SDL_GetError()); - sdl_close(); - return(0); - } + sdl_win = SDL_CreateWindowFrom((void *)hwndRender); + sdl_set_fs(video_fullscreen & 1); /* Make sure we get a clean exit. */ atexit(sdl_close); @@ -498,14 +463,9 @@ sdl_init_common(int flags) /* Register our renderer! */ video_setblit(sdl_blit); - sdl_fs = !!(flags & RENDERER_FULL_SCREEN); - sdl_enabled = 1; - sdl_mutex = SDL_CreateMutex(); - sdl_flags = flags; - return(1); } @@ -531,47 +491,6 @@ sdl_initho(HWND h) } -int -sdl_inits_fs(HWND h) -{ - return sdl_init_common(RENDERER_FULL_SCREEN); -} - - -int -sdl_inith_fs(HWND h) -{ - return sdl_init_common(RENDERER_FULL_SCREEN | RENDERER_HARDWARE); -} - - -int -sdl_initho_fs(HWND h) -{ - return sdl_init_common(RENDERER_FULL_SCREEN | RENDERER_HARDWARE | RENDERER_OPENGL); -} - - -void -sdl_reinit_texture() -{ - if ((sdl_render == NULL) || (sdl_flags == -1)) - return; - - SDL_DestroyTexture(sdl_tex); - SDL_DestroyRenderer(sdl_render); - if (sdl_flags & RENDERER_HARDWARE) { - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED); - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2"); - } else - sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); - sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, 2048, 2048); - SDL_SetWindowSize(sdl_win, cur_ww, cur_wh); - SDL_SetWindowPosition(sdl_win, cur_wx, cur_wy); -} - - int sdl_pause(void) { @@ -584,6 +503,9 @@ sdl_resize(int x, int y) { int ww = 0, wh = 0, wx = 0, wy = 0; + if (video_fullscreen & 2) + return; + if ((x == cur_w) && (y == cur_h)) return; @@ -594,7 +516,7 @@ sdl_resize(int x, int y) if (sdl_fs) { sdl_stretch(&ww, &wh, &wx, &wy); - MoveWindow(sdl_hwnd, wx, wy, ww, wh, TRUE); + MoveWindow(hwndRender, wx, wy, ww, wh, TRUE); } cur_w = x; @@ -605,6 +527,9 @@ sdl_resize(int x, int y) cur_ww = ww; cur_wh = wh; + SDL_SetWindowSize(sdl_win, cur_ww, cur_wh); + SDL_SetWindowPosition(sdl_win, cur_wx, cur_wy); + sdl_reinit_texture(); SDL_UnlockMutex(sdl_mutex); @@ -619,7 +544,11 @@ sdl_enable(int enable) SDL_LockMutex(sdl_mutex); sdl_enabled = enable; - if (enable) + + if (enable == 1) { + SDL_SetWindowSize(sdl_win, cur_ww, cur_wh); sdl_reinit_texture(); + } + SDL_UnlockMutex(sdl_mutex); } diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 5dd4026c5..f4cf7047f 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -28,6 +28,7 @@ #include #include #include +#include <86box/plat.h> #include <86box/86box.h> #include <86box/config.h> #include "../cpu/cpu.h" @@ -38,7 +39,6 @@ #include <86box/nvr.h> #include <86box/video.h> #include <86box/vid_ega.h> // for update_overscan -#include <86box/plat.h> #include <86box/plat_midi.h> #include <86box/plat_dynld.h> #include <86box/ui.h> @@ -373,6 +373,85 @@ plat_power_off(void) } +/* Catch WM_INPUT messages for 'current focus' window. */ +#if defined(__amd64__) || defined(__aarch64__) +static LRESULT CALLBACK +#else +static BOOL CALLBACK +#endif +input_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_INPUT: + if (infocus) { + UINT size = 0; + PRAWINPUT raw = NULL; + + /* Here we read the raw input data */ + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); + raw = (PRAWINPUT)malloc(size); + if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER)) == size) { + switch(raw->header.dwType) + { + case RIM_TYPEKEYBOARD: + keyboard_handle(raw); + break; + case RIM_TYPEMOUSE: + win_mouse_handle(raw); + break; + case RIM_TYPEHID: + win_joystick_handle(raw); + break; + } + } + free(raw); + } + break; + case WM_SETFOCUS: + infocus = 1; +#ifndef NO_KEYBOARD_HOOK + if (! hook_enabled) { + hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, + LowLevelKeyboardProc, + GetModuleHandle(NULL), + 0); + hook_enabled = 1; + } +#endif + break; + + case WM_KILLFOCUS: + infocus = 0; + plat_mouse_capture(0); +#ifndef NO_KEYBOARD_HOOK + if (hook_enabled) { + UnhookWindowsHookEx(hKeyboardHook); + hook_enabled = 0; + } +#endif + break; + + case WM_LBUTTONUP: + pclog("video_fullscreen = %i\n", video_fullscreen); + if (! video_fullscreen) + plat_mouse_capture(1); + break; + + case WM_MBUTTONUP: + if (mouse_get_buttons() < 3) + plat_mouse_capture(0); + break; + + default: + return(1); + /* return(CallWindowProc((WNDPROC)input_orig_proc, + hwnd, message, wParam, lParam)); */ + } + + return(0); +} + + static LRESULT CALLBACK MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -383,6 +462,9 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) int temp_x, temp_y; + if (input_proc(hwnd, message, wParam, lParam) == 0) + return(0); + switch (message) { case WM_CREATE: SetTimer(hwnd, TIMER_1SEC, 1000, NULL); @@ -571,6 +653,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) CheckMenuItem(hmenu, IDM_VID_SCALE_1X+scale, MF_UNCHECKED); scale = LOWORD(wParam) - IDM_VID_SCALE_1X; CheckMenuItem(hmenu, IDM_VID_SCALE_1X+scale, MF_CHECKED); + reset_screen_size(); device_force_redraw(); video_force_resize_set(1); config_save(); @@ -716,11 +799,10 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) GetWindowRect(hwndSBAR, &rect); sbar_height = rect.bottom - rect.top; rect_p = (RECT*)lParam; - if (vid_resize) { + if (vid_resize) MoveWindow(hwnd, rect_p->left, rect_p->top, rect_p->right - rect_p->left, rect_p->bottom - rect_p->top, TRUE); - } else if (!user_resize) { + else if (!user_resize) doresize = 1; - } break; case WM_SIZE: @@ -773,6 +855,9 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } plat_vidapi_enable(1); + plat_vidapi_enable(0); + plat_vidapi_enable(1); + config_save(); break; @@ -939,7 +1024,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_ACTIVATE: - if (wParam != WA_INACTIVE) { + if ((wParam != WA_INACTIVE) && !(video_fullscreen & 2)) { video_force_resize_set(1); plat_vidapi_enable(0); plat_vidapi_enable(1); @@ -966,6 +1051,38 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) static LRESULT CALLBACK SubWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_LBUTTONUP: + if (! video_fullscreen) + plat_mouse_capture(1); + break; + + case WM_MBUTTONUP: + if (mouse_get_buttons() < 3) + plat_mouse_capture(0); + break; + + default: + return(DefWindowProc(hwnd, message, wParam, lParam)); + } + + return(0); +} + + +static LRESULT CALLBACK +SDLMainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (input_proc(hwnd, message, wParam, lParam) == 0) + return(0); + + return(DefWindowProc(hwnd, message, wParam, lParam)); +} + + +static LRESULT CALLBACK +SDLSubWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { return(DefWindowProc(hwnd, message, wParam, lParam)); } @@ -1056,6 +1173,14 @@ ui_init(int nCmdShow) return(2); wincl.lpszClassName = SUB_CLASS_NAME; wincl.lpfnWndProc = SubWindowProcedure; + if (! RegisterClassEx(&wincl)) + return(2); + wincl.lpszClassName = SDL_CLASS_NAME; + wincl.lpfnWndProc = SDLMainWindowProcedure; + if (! RegisterClassEx(&wincl)) + return(2); + wincl.lpszClassName = SDL_SUB_CLASS_NAME; + wincl.lpfnWndProc = SDLSubWindowProcedure; if (! RegisterClassEx(&wincl)) return(2); @@ -1128,9 +1253,6 @@ ui_init(int nCmdShow) } keyboard_getkeymap(); - /* Set up the main window for RawInput. */ - plat_set_input(hwndMain); - /* Load the accelerator table */ haccel = LoadAccelerators(hinstance, ACCEL_NAME); if (haccel == NULL) { @@ -1149,7 +1271,7 @@ ui_init(int nCmdShow) ghMutex = CreateMutex(NULL, FALSE, NULL); /* Create the Machine Rendering window. */ - hwndRender = CreateWindow(L"STATIC", NULL, WS_CHILD|SS_BITMAP, + hwndRender = CreateWindow(/*L"STATIC"*/ SUB_CLASS_NAME, NULL, WS_CHILD|SS_BITMAP, 0, 0, 1, 1, hwnd, NULL, hinstance, NULL); MoveWindow(hwndRender, 0, 0, scrnsz_x, scrnsz_y, TRUE); @@ -1241,6 +1363,8 @@ ui_init(int nCmdShow) /* Close down the emulator. */ do_stop(); + UnregisterClass(SDL_SUB_CLASS_NAME, hinstance); + UnregisterClass(SDL_CLASS_NAME, hinstance); UnregisterClass(SUB_CLASS_NAME, hinstance); UnregisterClass(CLASS_NAME, hinstance); @@ -1384,100 +1508,3 @@ plat_mouse_capture(int on) mouse_capture = 0; } } - - -/* Catch WM_INPUT messages for 'current focus' window. */ -static LONG_PTR input_orig_proc; -static HWND input_orig_hwnd = NULL; -#if defined(__amd64__) || defined(__aarch64__) -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -input_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_INPUT: - if (infocus) { - UINT size = 0; - PRAWINPUT raw = NULL; - - /* Here we read the raw input data */ - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); - raw = (PRAWINPUT)malloc(size); - if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER)) == size) { - switch(raw->header.dwType) - { - case RIM_TYPEKEYBOARD: - keyboard_handle(raw); - break; - case RIM_TYPEMOUSE: - win_mouse_handle(raw); - break; - case RIM_TYPEHID: - win_joystick_handle(raw); - break; - } - } - free(raw); - } - break; - case WM_SETFOCUS: - infocus = 1; -#ifndef NO_KEYBOARD_HOOK - if (! hook_enabled) { - hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, - LowLevelKeyboardProc, - GetModuleHandle(NULL), - 0); - hook_enabled = 1; - } -#endif - break; - - case WM_KILLFOCUS: - infocus = 0; - plat_mouse_capture(0); -#ifndef NO_KEYBOARD_HOOK - if (hook_enabled) { - UnhookWindowsHookEx(hKeyboardHook); - hook_enabled = 0; - } -#endif - break; - - case WM_LBUTTONUP: - if (! video_fullscreen) - plat_mouse_capture(1); - break; - - case WM_MBUTTONUP: - if (mouse_get_buttons() < 3) - plat_mouse_capture(0); - break; - - default: - return(CallWindowProc((WNDPROC)input_orig_proc, - hwnd, message, wParam, lParam)); - } - - return(0); -} - - -/* Set up a handler for the 'currently active' window. */ -void -plat_set_input(HWND h) -{ - /* If needed, rest the old one first. */ - if (input_orig_hwnd != NULL) { - SetWindowLongPtr(input_orig_hwnd, GWLP_WNDPROC, - (LONG_PTR)input_orig_proc); - } - - /* Redirect the window procedure so we can catch WM_INPUT. */ - input_orig_proc = GetWindowLongPtr(h, GWLP_WNDPROC); - input_orig_hwnd = h; - SetWindowLongPtr(h, GWLP_WNDPROC, (LONG_PTR)&input_proc); - ImmAssociateContext(h, NULL); -}