diff --git a/src/device.c b/src/device.c index ed2e666..2ea72ca 100644 --- a/src/device.c +++ b/src/device.c @@ -9,7 +9,7 @@ * Implementation of the generic device interface to handle * all devices attached to the emulator. * - * Version: @(#)device.c 1.0.16 2018/10/14 + * Version: @(#)device.c 1.0.17 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -168,6 +168,10 @@ device_add(const device_t *d) old = device_current; device_current = (device_t *)d; + /* + * Do this so that a chained device_add will not identify the + * same ID its master device is already trying to assign. + */ devices[c] = (device_t *)d; if (d->init != NULL) { diff --git a/src/devices/disk/zip.c b/src/devices/disk/zip.c index 5791fb2..4fb732e 100644 --- a/src/devices/disk/zip.c +++ b/src/devices/disk/zip.c @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.c 1.0.21 2018/10/21 + * Version: @(#)zip.c 1.0.22 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1364,6 +1364,7 @@ zip_reset(void *p) dev->status = 0; dev->callback = 0LL; zip_set_callback(dev); + zip_set_signature(dev); dev->packet_status = 0xff; dev->unit_attention = 0; } @@ -1968,13 +1969,8 @@ zip_command(void *p, uint8_t *cdb) else zipbufferb[0] = 0x00; /*Hard disk*/ zipbufferb[1] = 0x80; /*Removable*/ - if (dev->drv->is_250) { - zipbufferb[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - zipbufferb[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; - } else { - zipbufferb[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - zipbufferb[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; - } + zipbufferb[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + zipbufferb[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; zipbufferb[4] = 31; if (dev->drv->bus_type == ZIP_BUS_SCSI) { zipbufferb[6] = 1; /* 16-bit transfers supported */ diff --git a/src/devices/floppy/fdd_td0.c b/src/devices/floppy/fdd_td0.c index 2c8f823..0f5b35e 100644 --- a/src/devices/floppy/fdd_td0.c +++ b/src/devices/floppy/fdd_td0.c @@ -8,7 +8,7 @@ * * Implementation of the Teledisk floppy image format. * - * Version: @(#)fdd_td0.c 1.0.9 2018/10/05 + * Version: @(#)fdd_td0.c 1.0.10 2018/10/24 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -365,9 +365,14 @@ state_reconst(td0dsk_t *state) k++; l = (j - k) * 2; - memcpy(&state->freq[k + 1], &state->freq[k], l); + /* + * NOTE: these *HAVE* to be memmove's as destination and + * source can overlap, which memcpy can't handle. + */ + memmove(&state->freq[k + 1], &state->freq[k], l); + state->freq[k] = f; - memcpy(&state->son[k + 1], &state->son[k], l); + memmove(&state->son[k + 1], &state->son[k], l); state->son[k] = i; } @@ -736,7 +741,7 @@ td0_initialize(int drive) offset += 3; switch (hs[8]) { default: - ERRLOG("TD0: image uses an unsupported sector data encoding\n"); + ERRLOG("TD0: image uses an unsupported sector data encoding: %i\n", (int)hs[8]); return(0); case 0: @@ -1114,6 +1119,24 @@ td0_init(void) } +static void +td0_abort(int drive) +{ + td0_t *dev = td0[drive]; + + if (dev->imagebuf) + free(dev->imagebuf); + if (dev->processed_buf) + free(dev->processed_buf); + if (dev->f) + fclose(dev->f); + + free(dev); + + td0[drive] = NULL; +} + + int td0_load(int drive, const wchar_t *fn) { @@ -1137,8 +1160,7 @@ td0_load(int drive, const wchar_t *fn) if (! dsk_identify(drive)) { ERRLOG("TD0: not a valid Teledisk image\n"); - fclose(dev->f); - dev->f = NULL; + td0_abort(drive); return(0); } else { DEBUG("TD0: valid Teledisk image\n"); @@ -1153,9 +1175,7 @@ td0_load(int drive, const wchar_t *fn) if (! td0_initialize(drive)) { ERRLOG("TD0: failed to initialize\n"); - fclose(dev->f); - free(dev->imagebuf); - free(dev->processed_buf); + td0_abort(drive); return(0); } @@ -1193,8 +1213,10 @@ td0_close(int drive) d86f_unregister(drive); - free(dev->imagebuf); - free(dev->processed_buf); + if (dev->imagebuf) + free(dev->imagebuf); + if (dev->processed_buf) + free(dev->processed_buf); for (i = 0; i < 256; i++) { for (j = 0; j < 2; j++) { diff --git a/src/devices/scsi/scsi_cdrom.c b/src/devices/scsi/scsi_cdrom.c index 270af98..b3a9763 100644 --- a/src/devices/scsi/scsi_cdrom.c +++ b/src/devices/scsi/scsi_cdrom.c @@ -8,7 +8,7 @@ * * Emulation of SCSI (and ATAPI) CD-ROM drives. * - * Version: @(#)scsi_cdrom.c 1.0.7 2018/10/22 + * Version: @(#)scsi_cdrom.c 1.0.8 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -1445,6 +1445,8 @@ scsi_cdrom_reset(void *p) set_callback(dev); + set_signature(dev); + dev->packet_status = 0xff; dev->unit_attention = 0xff; } diff --git a/src/devices/video/vid_genius.c b/src/devices/video/vid_genius.c index 3b77cdb..5f03270 100644 --- a/src/devices/video/vid_genius.c +++ b/src/devices/video/vid_genius.c @@ -63,15 +63,15 @@ * reducing the height of characters so they fit in an 8x12 cell * if necessary. * - * Version: @(#)vid_genius.c 1.0.7 2018/09/22 + * Version: @(#)vid_genius.c 1.0.8 2018/10/24 * * Authors: Fred N. van Kempen, * Miran Grca, - * Sarah Walker, + * John Elliott, * * Copyright 2017,2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2018 John Elliott. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/devices/video/vid_sigma.c b/src/devices/video/vid_sigma.c new file mode 100644 index 0000000..b00edfb --- /dev/null +++ b/src/devices/video/vid_sigma.c @@ -0,0 +1,963 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Emulation of the Sigma Color 400 video card. + * + * The Sigma Designs Color 400 is a video card from 1985, + * presumably intended as an EGA competitor. + * + * The hardware seems to have gone through various iterations; + * I've seen pictures of full-length and half-length versions. + * TH99 describes the jumpers / switches: + * + * + * + * The card is CGA-compatible at BIOS level, but to improve + * compatibility attempts to write to the CGA I/O ports at + * 0x3D0-0x3DF trigger an NMI. The card's BIOS handles the NMI + * and translates the CGA writes into commands to its own + * hardware at 0x2D0-0x2DF. (DIP switches on the card allow the + * base address to be changed, but since the BIOS dump I have + * doesn't support this I haven't emulated it. Likewise the + * BIOS ROM address can be changed, but I'm going with the + * default of 0xC0000). + * + * The BIOS still functions if the NMI system isn't operational. + * There doesn't seem to be a jumper or DIP switch to lock it + * out, but at startup the BIOS tests for its presence and + * configures itself to work or not as required. I've therefore + * added a configuration option to handle this. + * + * The card's real CRTC at 0x2D0/0x2D1 appears to be a 6845. + * One oddity is that all its horizontal counts are halved + * compared to what a real CGA uses; 40-column modes have a width + * of 20, and 80-column modes have a width of 40. This means that + * the CRTC cursor position (registers 14/15) can only address + * even-numbered columns, so the top bit of the control register + * at 0x2D9 is used to adjust the position. + * + * Version: @(#)vid_sigma.c 1.0.1 2018/10/24 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * John Elliott, + * + * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Miran Grca. + * Copyright 2018 John Elliott. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" +#include "../../timer.h" +#include "../../device.h" +#include "../../plat.h" +#include "../system/nmi.h" +#include "../system/pit.h" +#include "video.h" +#include "vid_cga.h" + + +#define FONT_ROM_PATH L"video/sigma/sigma400_font.rom" +#define BIOS_ROM_PATH L"video/sigma/sigma400_bios.rom" + + +/* 0x2D8: Mode register. Values written by the card BIOS are: + * Text 40x25: 0xA8 + * Text 80x25: 0xB9 + * Text 80x30: 0xB9 + * Text 80x50: 0x79 + * Graphics 320x200: 0x0F + * Graphics 640x200: 0x1F + * Graphics 640x400: 0x7F + * + * I have assumed this is a bitmap with the following meaning: + */ +#define MODE_80COLS 0x01 /* For text modes, 80 columns across */ +#define MODE_GRAPHICS 0x02 /* Graphics mode */ +#define MODE_NOBLINK 0x04 /* Disable blink? */ +#define MODE_ENABLE 0x08 /* Enable display */ +#define MODE_HRGFX 0x10 /* For graphics modes, 640 pixels across */ +#define MODE_640x400 0x40 /* 400-line graphics mode */ +#define MODE_FONT16 0x80 /* Use 16-pixel high font */ + +/* + * 0x2D9: Control register, with the following bits: + */ +#define CTL_CURSOR 0x80 /* Low bit of cursor position */ +#define CTL_NMI 0x20 /* Writes to 0x3D0-0x3DF trigger NMI */ +#define CTL_CLEAR_LPEN 0x08 /* Strobe 0 to clear lightpen latch */ +#define CTL_SET_LPEN 0x04 /* Strobe 0 to set lightpen latch */ +#define CTL_PALETTE 0x01 /* 0x2DE writes to palette (1) or plane (0) */ + +/* + * The card BIOS seems to support two variants of the hardware: One where + * bits 2 and 3 are normally 1 and are set to 0 to set/clear the latch, and + * one where they are normally 0 and are set to 1. Behaviour is selected by + * whether the byte at C000:17FFh is greater than 2Fh. + * + * 0x2DA: Status register. + */ +#define STATUS_CURSOR 0x80 /* Last value written to bit 7 of 0x2D9 */ +#define STATUS_NMI 0x20 /* Last value written to bit 5 of 0x2D9 */ +#define STATUS_RETR_V 0x10 /* Vertical retrace */ +#define STATUS_LPEN_T 0x04 /* Lightpen switch is off */ +#define STATUS_LPEN_A 0x02 /* Edge from lightpen has set trigger */ +#define STATUS_RETR_H 0x01 /* Horizontal retrace */ + +/* + * 0x2DB: On read: Byte written to the card that triggered NMI + * 0x2DB: On write: Resets the 'card raised NMI' flag. + * 0x2DC: On read: Bit 7 set if the card raised NMI. If so, bits 0-3 + * give the low 4 bits of the I/O port address. + * 0x2DC: On write: Resets the NMI. + * 0x2DD: Memory paging. The memory from 0xC1800 to 0xC1FFF can be either: + * + * > ROM: A 128 character 8x16 font for use in graphics modes + * > RAM: Use by the video BIOS to hold its settings. + * + * Reading port 2DD switches to ROM. Bit 7 of the value read gives the + * previous paging state: bit 7 set if ROM was paged, clear if RAM was + * paged. + * + * Writing port 2DD switches to RAM. + * + * 0x2DE: Meaning depends on bottom bit of value written to port 0x2D9. + * Bit 0 set: Write to palette. High 4 bits of value = register, + * low 4 bits = RGBI values (active low) + * Bit 0 clear: Write to plane select. Low 2 bits of value select + * plane 0-3 + */ + + +#define COMPOSITE_OLD 0 +#define COMPOSITE_NEW 1 + + +typedef struct { + mem_map_t mapping, + bios_ram; + + rom_t bios_rom; + + uint8_t crtc[32]; /* CRTC: Real values */ + + uint8_t lastport; /* Last I/O port written */ + uint8_t lastwrite; /* Value written to that port */ + uint8_t sigma_ctl; /* Controls register: + * Bit 7 is low bit of cursor position + * Bit 5 set if writes to CGA ports trigger NMI + * Bit 3 clears lightpen latch + * Bit 2 sets lightpen latch + * Bit 1 controls meaning of port 2DE + */ + uint8_t enable_nmi; /* Enable the NMI mechanism for CGA emulation?*/ + uint8_t rom_paged; /* Is ROM paged in at 0xC1800? */ + + uint8_t crtc_value; /* Value to return from a CRTC register read */ + + uint8_t sigmastat; /* Status register [0x2DA] */ + + uint8_t sigmamode; /* Mode control register [0x2D8] */ + + uint16_t ma, maback; + + int crtcreg; /* CRTC: Real selected register */ + + int linepos, displine; + int sc, vc; + int cgadispon; + int con, coff, cursoron, cgablink; + int vsynctime, vadj; + int oddeven; + + int64_t dispontime, dispofftime; + + int firstline, lastline; + + int drawcursor; + + int plane; + int revision; + + int64_t vidtime; + + uint8_t *vram; + uint8_t bram[2048]; + uint8_t palette[16]; +} sigma_t; + + +static const uint8_t crtcmask[32] = { + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const video_timings_t sigma_timing = {VID_ISA,8,16,32,8,16,32}; + + +static void +recalc_timings(sigma_t *dev) +{ + double disptime; + double _dispontime, _dispofftime; + + if (dev->sigmamode & MODE_80COLS) { + disptime = (dev->crtc[0] + 1) << 1; + _dispontime = (dev->crtc[1]) << 1; + } else { + disptime = (dev->crtc[0] + 1) << 2; + _dispontime = dev->crtc[1] << 2; + } + + _dispofftime = disptime - _dispontime; + _dispontime *= CGACONST; + _dispofftime *= CGACONST; + + dev->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); +} + + +static void +sigma_out(uint16_t port, uint8_t val, void *priv) +{ + sigma_t *dev = (sigma_t *)priv; + uint8_t old; + + if (port >= 0x3d0 && port < 0x3e0) { + dev->lastport = port & 0x0f; + dev->lastwrite = val; + + /* If set to NMI on video I/O... */ + if (dev->enable_nmi && (dev->sigma_ctl & CTL_NMI)) { + dev->lastport |= 0x80; /* Card raised NMI */ + nmi = 1; + } + + /* For CRTC emulation, the card BIOS sets the value to be + * read from port 0x3D1 like this */ + if (port == 0x3d1) + dev->crtc_value = val; + + return; + } + + switch (port) { + case 0x2d0: + case 0x2d2: + case 0x2d4: + case 0x2d6: + dev->crtcreg = val & 31; + break; + + case 0x2d1: + case 0x2d3: + case 0x2d5: + case 0x2d7: + old = dev->crtc[dev->crtcreg]; + dev->crtc[dev->crtcreg] = val & crtcmask[dev->crtcreg]; + if (old != val) { + if (dev->crtcreg < 0xe || dev->crtcreg > 0x10) { + fullchange = changeframecount; + recalc_timings(dev); + } + } + break; + + case 0x2d8: + dev->sigmamode = val; + break; + + case 0x2d9: + dev->sigma_ctl = val; + break; + + case 0x2db: + dev->lastport &= 0x7F; + break; + + case 0x2dc: /* Reset NMI */ + nmi = 0; + dev->lastport &= 0x7F; + break; + + case 0x2dd: /* Page in RAM at 0xC1800 */ + if (dev->rom_paged != 0) + mmu_invalidate(0xc0000); + dev->rom_paged = 0; + break; + + case 0x2de: + if (dev->sigma_ctl & CTL_PALETTE) + dev->palette[val >> 4] = (val & 0x0f) ^ 0x0f; + else + dev->plane = val & 3; + break; + } +} + + +static uint8_t +sigma_in(uint16_t port, void *priv) +{ + sigma_t *dev = (sigma_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x2d0: + case 0x2d2: + case 0x2d4: + case 0x2d6: + ret = dev->crtcreg; + break; + + case 0x2d1: + case 0x2d3: + case 0x2d5: + case 0x2d7: + ret = dev->crtc[dev->crtcreg & 0x1f]; + break; + + case 0x2da: + ret = (dev->sigma_ctl & 0xe0) | (dev->sigmastat & 0x1f); + break; + + case 0x2db: + ret = dev->lastwrite; /* Value that triggered NMI */ + break; + + case 0x2dc: + ret = dev->lastport; /* Port that triggered NMI */ + break; + + case 0x2dd: /* Page in ROM at 0xC1800 */ + ret = (dev->rom_paged ? 0x80 : 0); + if (dev->rom_paged != 0x80) + mmu_invalidate(0xc0000); + dev->rom_paged = 0x80; + break; + + case 0x3d1: + case 0x3d3: + case 0x3d5: + case 0x3d7: + ret = dev->crtc_value; + break; + + /* + * For CGA compatibility we have to return something palatable + * on this port. On a real card this functionality can be turned + * on or off with SW1/6. + */ + case 0x3da: + ret = dev->sigmastat & 7; + if (dev->sigmastat & STATUS_RETR_V) ret |= 8; + break; + } + + return ret; +} + + +static void +sigma_write(uint32_t addr, uint8_t val, void *priv) +{ + sigma_t *dev = (sigma_t *)priv; + + cycles -= 4; + + dev->vram[dev->plane * 0x8000 + (addr & 0x7fff)] = val; +} + + +static uint8_t +sigma_read(uint32_t addr, void *priv) +{ + sigma_t *dev = (sigma_t *)priv; + + cycles -= 4; + + return dev->vram[dev->plane * 0x8000 + (addr & 0x7fff)]; +} + + +static void +sigma_bwrite(uint32_t addr, uint8_t val, void *priv) +{ + sigma_t *dev = (sigma_t *)priv; + + addr &= 0x3fff; +#if 0 + if ((addr >= 0x1800) && !dev->rom_paged && (addr < 0x2000)) +#endif + if ((addr < 0x1800) || dev->rom_paged || (addr >= 0x2000)) + ; + else + dev->bram[addr & 0x7ff] = val; +} + + +static uint8_t +sigma_bread(uint32_t addr, void *priv) +{ + sigma_t *dev = (sigma_t *)priv; + uint8_t ret; + + addr &= 0x3fff; + if (addr >= 0x2000) + return 0xff; + + if (addr < 0x1800 || dev->rom_paged) + ret = dev->bios_rom.rom[addr & 0x1fff]; + else + ret = dev->bram[addr & 0x7ff]; + + return ret; +} + + +/* Render a line in 80-column text mode */ +static void +sigma_text80(sigma_t *dev) +{ + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)); + uint16_t ma = ((dev->ma & 0x3fff) << 1); + uint8_t *vram = dev->vram + (ma << 1); + int drawcursor, x, c; + uint8_t chr, attr; + uint32_t cols[4]; + + ca = ca << 1; + if (dev->sigma_ctl & CTL_CURSOR) + ++ca; + ca &= 0x3fff; + + /* The Sigma 400 seems to use screen widths stated in words + (40 for 80-column, 20 for 40-column) */ + for (x = 0; x < (dev->crtc[1] << 1); x++) { + chr = vram[x << 1]; + attr = vram[(x << 1) + 1]; + drawcursor = ((ma == ca) && dev->con && dev->cursoron); + + if (! (dev->sigmamode & MODE_NOBLINK)) { + cols[1] = (attr & 15) | 16; + cols[0] = ((attr >> 4) & 7) | 16; + if ((dev->cgablink & 8) && (attr & 0x80) && !dev->drawcursor) + cols[1] = cols[0]; + } else { /* No blink */ + cols[1] = (attr & 15) | 16; + cols[0] = (attr >> 4) | 16; + } + + if (drawcursor && !(x & 1)) { + for (c = 0; c < 8; c++) { + if (dev->sigmamode & MODE_FONT16) + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f; + else + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(fontdat[chr][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f; + } + } else { + for (c = 0; c < 8; c++) { + if (dev->sigmamode & MODE_FONT16) + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + else + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(fontdat[chr][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + ++ma; + } + + dev->ma += dev->crtc[1]; +} + + +/* Render a line in 40-column text mode */ +static void +sigma_text40(sigma_t *dev) +{ + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)); + uint16_t ma = ((dev->ma & 0x3FFF) << 1); + uint8_t *vram = dev->vram + ((ma << 1) & 0x3FFF); + int drawcursor, x, c; + uint8_t chr, attr; + uint32_t cols[4]; + + ca = ca << 1; + if (dev->sigma_ctl & CTL_CURSOR) + ++ca; + ca &= 0x3fff; + + /* The Sigma 400 seems to use screen widths stated in words + (40 for 80-column, 20 for 40-column) */ + for (x = 0; x < (dev->crtc[1] << 1); x++) { + chr = vram[x << 1]; + attr = vram[(x << 1) + 1]; + drawcursor = ((ma == ca) && dev->con && dev->cursoron); + + if (!(dev->sigmamode & MODE_NOBLINK)) { + cols[1] = (attr & 15) | 16; + cols[0] = ((attr >> 4) & 7) | 16; + if ((dev->cgablink & 8) && (attr & 0x80) && !dev->drawcursor) + cols[1] = cols[0]; + } else { /* No blink */ + cols[1] = (attr & 15) | 16; + cols[0] = (attr >> 4) | 16; + } + + if (drawcursor) { + for (c = 0; c < 8; c++) { + buffer->line[dev->displine][(x << 4) + 2*c + 8] = + buffer->line[dev->displine][(x << 4) + 2*c + 9] = cols[(fontdatm[chr][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f; + } + } else { + for (c = 0; c < 8; c++) { + buffer->line[dev->displine][(x << 4) + 2*c + 8] = + buffer->line[dev->displine][(x << 4) + 2*c + 9] = cols[(fontdatm[chr][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + ma++; + } + + dev->ma += dev->crtc[1]; +} + + +/* Draw a line in the 640x400 graphics mode */ +static void +sigma_gfx400(sigma_t *dev) +{ + uint8_t *vram = &dev->vram[((dev->ma << 1) & 0x1fff) + (dev->sc & 3) * 0x2000]; + uint8_t mask, col, c; + uint8_t plane[4]; + int x; + + for (x = 0; x < (dev->crtc[1] << 1); x++) { + plane[0] = vram[x]; + plane[1] = vram[0x8000 + x]; + plane[2] = vram[0x10000 + x]; + plane[3] = vram[0x18000 + x]; + + for (c = 0, mask = 0x80; c < 8; c++, mask >>= 1) { + col = ((plane[3] & mask) ? 8 : 0) | + ((plane[2] & mask) ? 4 : 0) | + ((plane[1] & mask) ? 2 : 0) | + ((plane[0] & mask) ? 1 : 0); + col |= 16; + buffer->line[dev->displine][(x << 3) + c + 8] = col; + } + + if (x & 1) dev->ma++; + } +} + + +/* Draw a line in the 640x200 graphics mode. + * This is actually a 640x200x16 mode; on startup, the BIOS selects plane 2, + * blanks the other planes, and sets palette ink 4 to white. Pixels plotted + * in plane 2 come out in white, others black; but by programming the palette + * and plane registers manually you can get the full resolution. */ +static void +sigma_gfx200(sigma_t *dev) +{ + uint8_t *vram = &dev->vram[((dev->ma << 1) & 0x1fff) + (dev->sc & 2) * 0x1000]; + uint8_t mask, col, c; + uint8_t plane[4]; + int x; + + for (x = 0; x < (dev->crtc[1] << 1); x++) { + plane[0] = vram[x]; + plane[1] = vram[0x8000 + x]; + plane[2] = vram[0x10000 + x]; + plane[3] = vram[0x18000 + x]; + + for (c = 0, mask = 0x80; c < 8; c++, mask >>= 1) { + col = ((plane[3] & mask) ? 8 : 0) | + ((plane[2] & mask) ? 4 : 0) | + ((plane[1] & mask) ? 2 : 0) | + ((plane[0] & mask) ? 1 : 0); + col |= 16; + buffer->line[dev->displine][(x << 3) + c + 8] = col; + } + + if (x & 1) dev->ma++; + } +} + + +/* Draw a line in the 320x200 graphics mode */ +static void +sigma_gfx4col(sigma_t *dev) +{ + uint8_t *vram = &dev->vram[((dev->ma << 1) & 0x1fff) + (dev->sc & 2) * 0x1000]; + uint8_t mask, col, c; + uint8_t plane[4]; + int x; + + for (x = 0; x < (dev->crtc[1] << 1); x++) { + plane[0] = vram[x]; + plane[1] = vram[0x8000 + x]; + plane[2] = vram[0x10000 + x]; + plane[3] = vram[0x18000 + x]; + + mask = 0x80; + for (c = 0; c < 4; c++) { + col = ((plane[3] & mask) ? 2 : 0) | + ((plane[2] & mask) ? 1 : 0); + mask = mask >> 1; + col |= ((plane[3] & mask) ? 8 : 0) | + ((plane[2] & mask) ? 4 : 0); + col |= 16; + mask = mask >> 1; + + buffer->line[dev->displine][(x << 3) + (c << 1) + 8] = + buffer->line[dev->displine][(x << 3) + (c << 1) + 9] = col; + } + + if (x & 1) dev->ma++; + } +} + + +static void +sigma_poll(void *priv) +{ + sigma_t *dev = (sigma_t *)priv; + uint32_t cols[4]; + int oldsc, oldvc; + int x, c; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->sigmastat |= STATUS_RETR_H; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = ((dev->sc << 1) + dev->oddeven) & 7; + if (dev->cgadispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } + dev->lastline = dev->displine; + + cols[0] = 16; + + /* Left overscan */ + for (c = 0; c < 8; c++) { + buffer->line[dev->displine][c] = cols[0]; + if (dev->sigmamode & MODE_80COLS) + buffer->line[dev->displine][c + (dev->crtc[1] << 4) + 8] = cols[0]; + else + buffer->line[dev->displine][c + (dev->crtc[1] << 5) + 8] = cols[0]; + } + + if (dev->sigmamode & MODE_GRAPHICS) { + if (dev->sigmamode & MODE_640x400) + sigma_gfx400(dev); + else if (dev->sigmamode & MODE_HRGFX) + sigma_gfx200(dev); + else + sigma_gfx4col(dev); + } else { /* Text modes */ + if (dev->sigmamode & MODE_80COLS) + sigma_text80(dev); + else + sigma_text40(dev); + } + } else { + cols[0] = 16; + if (dev->sigmamode & MODE_80COLS) + cga_hline(buffer, 0, dev->displine, (dev->crtc[1] << 4) + 16, cols[0]); + else + cga_hline(buffer, 0, dev->displine, (dev->crtc[1] << 5) + 16, cols[0]); + } + + if (dev->sigmamode & MODE_80COLS) + x = (dev->crtc[1] << 4) + 16; + else + x = (dev->crtc[1] << 5) + 16; + + for (c = 0; c < x; c++) + buffer->line[dev->displine][c] = dev->palette[buffer->line[dev->displine][c] & 0xf] | 16; + + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->sigmastat |= STATUS_RETR_V; + dev->displine++; + if (dev->displine >= 560) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (!dev->vsynctime) + dev->sigmastat &= ~STATUS_RETR_V; + } + if (dev->sc == (dev->crtc[11] & 31) || + ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + if ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1)) + dev->maback = dev->ma; + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (!dev->vadj) { + dev->cgadispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9]) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + + if (dev->vc == dev->crtc[6]) + dev->cgadispon = 0; + + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) dev->cgadispon = 1; + if (!dev->vadj) dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->cgablink & 8; + } + + if (dev->vc == dev->crtc[7]) { + dev->cgadispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if (dev->sigmamode & MODE_80COLS) + x = (dev->crtc[1] << 4) + 16; + else + x = (dev->crtc[1] << 5) + 16; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || + video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) + xsize = 656; + if (ysize < 32) + ysize = 200; + + if (ysize <= 250) + set_screen_size(xsize, (ysize << 1) + 16); + else + set_screen_size(xsize, ysize + 8); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + video_blit_memtoscreen_8(0, dev->firstline - 4, 0, (dev->lastline - dev->firstline) + 8, xsize, (dev->lastline - dev->firstline) + 8); + frames++; + + video_res_x = xsize - 16; + video_res_y = ysize; + if (dev->sigmamode & MODE_GRAPHICS) { + if (dev->sigmamode & (MODE_HRGFX | MODE_640x400)) + video_bpp = 1; + else { + video_res_x /= 2; + video_bpp = 2; + } + } else if (dev->sigmamode & MODE_80COLS) { + /* 80-column text */ + video_res_x /= 8; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } else { + /* 40-column text */ + video_res_x /= 16; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->cgablink++; + dev->oddeven ^= 1; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + if (dev->cgadispon) + dev->sigmastat &= ~STATUS_RETR_H; + if ((dev->sc == (dev->crtc[10] & 31) || + ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + } +} + + +static void * +sigma_init(const device_t *info) +{ + sigma_t *dev = malloc(sizeof(sigma_t)); + memset(dev, 0, sizeof(sigma_t)); + + dev->enable_nmi = device_get_config_int("enable_nmi"); + + cga_palette = device_get_config_int("rgb_type") << 1; + if (cga_palette > 6) + cga_palette = 0; + cgapal_rebuild(); + + dev->vram = malloc(0x8000 * 4); + + mem_map_add(&dev->mapping, 0xb8000, 0x08000, + sigma_read,NULL,NULL, sigma_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + video_load_font(FONT_ROM_PATH, 7); + + rom_init(&dev->bios_rom, BIOS_ROM_PATH, + 0xc0000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + + /* + * The BIOS ROM is overlaid by RAM, so remove its default + * mapping and access it through sigma_bread/sigma_bwrite. + */ + mem_map_disable(&dev->bios_rom.mapping); + memcpy(dev->bram, &dev->bios_rom.rom[0x1800], 0x0800); + + mem_map_add(&dev->bios_ram, 0xc1800, 0x0800, + sigma_bread,NULL,NULL, sigma_bwrite,NULL,NULL, + dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03d0, 16, + sigma_in,NULL,NULL, sigma_out,NULL,NULL, dev); + io_sethandler(0x02d0, 16, + sigma_in,NULL,NULL, sigma_out,NULL,NULL, dev); + + timer_add(sigma_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + /* Start with ROM paged in, BIOS RAM paged out */ + dev->rom_paged = 0x80; + + if (dev->enable_nmi) + dev->sigmastat = STATUS_LPEN_T; + + video_inform(VID_TYPE_CGA, &sigma_timing); + + return dev; +} + + +static void +sigma_close(void *priv) +{ + sigma_t *dev = (sigma_t *)priv; + + free(dev->vram); + + free(dev); +} + + +void +speed_changed(void *priv) +{ + sigma_t *dev = (sigma_t *)priv; + + recalc_timings(dev); +} + + +static int +sigma_available(void) +{ + return((rom_present(FONT_ROM_PATH) && rom_present(BIOS_ROM_PATH))); +} + + +static const device_config_t sigma_config[] = { + { + "rgb_type", "RGB type", CONFIG_SELECTION, "", 0, + { + { + "Color", 0 + }, + { + "Green Monochrome", 1 + }, + { + "Amber Monochrome", 2 + }, + { + "Gray Monochrome", 3 + }, + { + "Color (no brown)", 4 + }, + { + "" + } + } + }, + { + "enable_nmi", "Enable NMI for CGA emulation", CONFIG_BINARY, "", 1 + }, + { + "", "", -1 + } +}; + + +const device_t sigma_device = { + "Sigma Color 400", + DEVICE_ISA, + 0, + sigma_init, sigma_close, NULL, + sigma_available, + speed_changed, + NULL, + NULL, + sigma_config +}; diff --git a/src/devices/video/video.c b/src/devices/video/video.c index ac697d4..b488eca 100644 --- a/src/devices/video/video.c +++ b/src/devices/video/video.c @@ -40,7 +40,7 @@ * W = 3 bus clocks * L = 4 bus clocks * - * Version: @(#)video.c 1.0.20 2018/10/20 + * Version: @(#)video.c 1.0.21 2018/10/24 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -893,18 +893,18 @@ video_load_font(const wchar_t *s, int format) case 5: /* Toshiba 3100e */ for (d = 0; d < 2048; d += 512) { /* Four languages... */ for (c = d; c < d+256; c++) - fread(&fontdatm[c][8], 1, 8, fp); + (void)fread(&fontdatm[c][8], 1, 8, fp); for (c = d+256; c < d+512; c++) - fread(&fontdatm[c][8], 1, 8, fp); + (void)fread(&fontdatm[c][8], 1, 8, fp); for (c = d; c < d+256; c++) - fread(&fontdatm[c][0], 1, 8, fp); + (void)fread(&fontdatm[c][0], 1, 8, fp); for (c = d+256; c < d+512; c++) - fread(&fontdatm[c][0], 1, 8, fp); - fseek(fp, 4096, SEEK_CUR); /* Skip blank section */ + (void)fread(&fontdatm[c][0], 1, 8, fp); + (void)fseek(fp, 4096, SEEK_CUR); /* Skip blank section */ for (c = d; c < d+256; c++) - fread(&fontdat[c][0], 1, 8, fp); + (void)fread(&fontdat[c][0], 1, 8, fp); for (c = d+256; c < d+512; c++) - fread(&fontdat[c][0], 1, 8, fp); + (void)fread(&fontdat[c][0], 1, 8, fp); } break; @@ -920,6 +920,18 @@ video_load_font(const wchar_t *s, int format) fontdatksc5601[c].chr[d] = fgetc(fp); } break; + + case 7: /* Sigma Color 400 */ + /* The first 4K of the character ROM holds an 8x8 font. */ + for (c = 0; c < 256; c++) { + (void)fread(&fontdat[c][0], 1, 8, fp); + (void)fseek(fp, 8, SEEK_CUR); + } + + /* The second 4K holds an 8x16 font. */ + for (c = 0; c < 256; c++) + (void)fread(&fontdatm[c][0], 1, 16, fp); + break; } (void)fclose(fp); diff --git a/src/devices/video/video.h b/src/devices/video/video.h index 4326fc3..b799613 100644 --- a/src/devices/video/video.h +++ b/src/devices/video/video.h @@ -8,7 +8,7 @@ * * Definitions for the video controller module. * - * Version: @(#)video.h 1.0.20 2018/10/22 + * Version: @(#)video.h 1.0.21 2018/10/24 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -272,6 +272,9 @@ extern const device_t s3_virge_375_pci_device; extern const device_t s3_virge_375_4_vlb_device; extern const device_t s3_virge_375_4_pci_device; +/* Sigma Designs cards. */ +extern const device_t sigma_device; + /* Trident 8900 series cards. */ extern const device_t tvga8900d_device; diff --git a/src/devices/video/video_dev.c b/src/devices/video/video_dev.c index 92e097c..ff9bf6d 100644 --- a/src/devices/video/video_dev.c +++ b/src/devices/video/video_dev.c @@ -12,7 +12,7 @@ * "extern" reference to its device into the video.h file, * and add an entry for it into the table here. * - * Version: @(#)video_dev.c 1.0.26 2018/10/22 + * Version: @(#)video_dev.c 1.0.27 2018/10/24 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -101,6 +101,7 @@ static const struct { { "oti067", &oti067_device }, { "oti077", &oti077_device }, { "pvga1a", ¶dise_pvga1a_device }, + { "sigma400", &sigma_device }, { "wd90c11", ¶dise_wd90c11_device }, { "wd90c30", ¶dise_wd90c30_device }, { "plantronics", &colorplus_device }, diff --git a/src/ui/lang/VARCem-NO.str b/src/ui/lang/VARCem-NO.str index 74253f5..76fa420 100644 --- a/src/ui/lang/VARCem-NO.str +++ b/src/ui/lang/VARCem-NO.str @@ -8,7 +8,7 @@ * * String definitions for "Norwegian (Norway)" language. * - * Version: @(#)VARCem-NO.str 1.0.5 2018/10/18 + * Version: @(#)VARCem-NO.str 1.0.6 2018/10/25 * * Author: Fred N. van Kempen, * Tore Sinding Bekkedal, # @@ -705,6 +705,7 @@ VIDOBJ := video.o \ vid_hercules.o vid_herculesplus.o vid_incolor.o \ vid_colorplus.o \ vid_genius.o \ + vid_sigma.o \ vid_wy700.o \ vid_ega.o vid_ega_render.o \ vid_svga.o vid_svga_render.o \ diff --git a/src/win/msvc/Makefile.VC b/src/win/msvc/Makefile.VC index 1873b28..5ddb671 100644 --- a/src/win/msvc/Makefile.VC +++ b/src/win/msvc/Makefile.VC @@ -8,7 +8,7 @@ # # Makefile for Windows using Visual Studio 2015. # -# Version: @(#)Makefile.VC 1.0.50 2018/10/24 +# Version: @(#)Makefile.VC 1.0.51 2018/10/24 # # Author: Fred N. van Kempen, # @@ -279,8 +279,8 @@ CXXOPTS := -EHsc DOPTS := ifeq ($(X64), y) LOPTS := -MACHINE:$(ARCH) -LIBPATH:win\msvc\Lib\$(ARCH) -#LOPTS_C := -SUBSYSTEM:CONSOLE -#LOPTS_W := -SUBSYSTEM:WINDOWS +LOPTS_C := -SUBSYSTEM:CONSOLE +LOPTS_W := -SUBSYSTEM:WINDOWS else LOPTS := -MACHINE:$(ARCH) -LIBPATH:win\msvc\Lib\$(ARCH) LOPTS_C := -SUBSYSTEM:CONSOLE,5.01 @@ -680,6 +680,7 @@ VIDOBJ := video.obj \ vid_hercules.obj vid_herculesplus.obj vid_incolor.obj \ vid_colorplus.obj \ vid_genius.obj \ + vid_sigma.obj \ vid_wy700.obj \ vid_ega.obj vid_ega_render.obj \ vid_svga.obj vid_svga_render.obj \ diff --git a/src/win/win.h b/src/win/win.h index 599a930..05863d6 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -10,7 +10,7 @@ * only things used globally within the Windows platform; the * generic platform defintions are in the plat.h file. * - * Version: @(#)win.h 1.0.22 2018/10/24 + * Version: @(#)win.h 1.0.23 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -69,6 +69,9 @@ #define WM_HARD_RESET WM_USER+5 #define WM_SHUTDOWN WM_USER+6 #define WM_CTRLALTDEL WM_USER+7 +#define WM_SEND_HWND WM_USER+8 /* send main window handle */ +#define WM_SEND_STATUS WM_USER+9 /* pause/resume status in WPARAM */ +#define WM_SEND_SSTATUS WM_USER+10 /* settings status: WPARAM 1=open */ /* Status bar definitions. */ diff --git a/src/win/win_about.c b/src/win/win_about.c index 612a6b3..8b6e0a2 100644 --- a/src/win/win_about.c +++ b/src/win/win_about.c @@ -12,7 +12,7 @@ * 24bit image would be preferred, but we cant use LoadImage * for those (and keep transparency...) * - * Version: @(#)win_about.c 1.0.11 2018/10/24 + * Version: @(#)win_about.c 1.0.12 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -256,12 +256,12 @@ about_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) void dlg_about(void) { - DialogBox(plat_lang_dll(), (LPCTSTR)DLG_ABOUT, hwndMain, about_proc); + DialogBox(plat_lang_dll(), (LPCWSTR)DLG_ABOUT, hwndMain, about_proc); } void dlg_localize(void) { - DialogBox(plat_lang_dll(), (LPCTSTR)DLG_LOCALIZE, hwndMain, localize_proc); + DialogBox(plat_lang_dll(), (LPCWSTR)DLG_LOCALIZE, hwndMain, localize_proc); } diff --git a/src/win/win_new_image.c b/src/win/win_new_image.c index e80ad84..9bf597c 100644 --- a/src/win/win_new_image.c +++ b/src/win/win_new_image.c @@ -8,7 +8,7 @@ * * Implementation of the New Floppy/ZIP Image dialog. * - * Version: @(#)win_new_image.c 1.0.21 2018/10/24 + * Version: @(#)win_new_image.c 1.0.22 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -268,5 +268,5 @@ dlg_new_image(int drive, int part, int zip) drive_id = drive; sb_part = part; - DialogBox(plat_lang_dll(), (LPCTSTR)DLG_NEW_FLOPPY, hwndMain, dlg_proc); + DialogBox(plat_lang_dll(), (LPCWSTR)DLG_NEW_FLOPPY, hwndMain, dlg_proc); } diff --git a/src/win/win_settings.c b/src/win/win_settings.c index cc4b734..c1704f0 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings.c 1.0.37 2018/10/24 + * Version: @(#)win_settings.c 1.0.37 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -559,7 +559,12 @@ image_list_init(HWND hwndList) for (i = 0; i < PAGE_MAX; i++) { - hiconItem = LoadIcon(hInstance, (LPCWSTR)icons[i]); +#if (defined(_MSC_VER) && defined(_M_X64)) || \ + (defined(__GNUC__) && defined(__amd64__)) + hiconItem = LoadIcon(hInstance, (LPCWSTR)((uint64_t)icons[i])); +#else + hiconItem = LoadIcon(hInstance, (LPCWSTR)((uint32_t)icons[i])); +#endif ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); } @@ -592,6 +597,49 @@ insert_categories(HWND hwndList) } +#ifdef USE_MANAGER +static void +communicate_closure(void) +{ + if (source_hwnd) + PostMessage((HWND)(uintptr_t)source_hwnd, + WM_SEND_SSTATUS, (WPARAM)0, (LPARAM)hwndMain); +} +#endif + + +static WIN_RESULT CALLBACK +settings_confirm(HWND hdlg, int button) +{ + int i; + + SendMessage(hwndChildDialog, WM_SAVE_CFG, 0, 0); + + if (ask_sure) { + i = msgbox_reset(); + if (i == 0) { + /* CANCEL, just kidding! */ + return(FALSE); + } + } else + i = 2; + + if (i == 2) { + /* YES, reset system. */ + settings_save(); + } + + DestroyWindow(hwndChildDialog); + EndDialog(hdlg, i); + +#ifdef USE_MANAGER + communicate_closure(); +#endif + + return button ? FALSE : TRUE; +} + + static WIN_RESULT CALLBACK dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -630,33 +678,21 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) } break; + case WM_CLOSE: + return settings_confirm(hdlg, 0); + case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: - SendMessage(hwndChildDialog, WM_SAVE_CFG, 0, 0); - if (ask_sure) { - i = msgbox_reset(); - if (i == 0) { - /* CANCEL, just kidding! */ - return(FALSE); - } - } else { - i = 2; - } - - if (i == 2) { - /* YES, reset system. */ - settings_save(); - } - - DestroyWindow(hwndChildDialog); - EndDialog(hdlg, i); - return(TRUE); + return settings_confirm(hdlg, 1); case IDCANCEL: /* CANCEL, just kidding! */ DestroyWindow(hwndChildDialog); EndDialog(hdlg, 0); +#ifdef USE_MANAGER + communicate_closure(); +#endif return(TRUE); } break; @@ -718,6 +754,12 @@ dlg_settings(int ask) { int i; +#ifdef USE_MANAGER + if (source_hwnd) + PostMessage((HWND) (uintptr_t) source_hwnd, + WM_SEND_SSTATUS, (WPARAM)1, (LPARAM)hwndMain; +#endif + /* * This looks weird here, but we have to do it * before we open up the Settings dialog, else @@ -736,7 +778,8 @@ dlg_settings(int ask) INFO("A total of %i machines are available.\n", i); ask_sure = ask; - i = DialogBox(plat_lang_dll(), (LPCWSTR)DLG_CONFIG, hwndMain, dlg_proc); + i = (int)DialogBox(plat_lang_dll(), + (LPCWSTR)DLG_CONFIG, hwndMain, dlg_proc); return(i); } diff --git a/src/win/win_settings_floppy.h b/src/win/win_settings_floppy.h index 7ffc43c..c66034b 100644 --- a/src/win/win_settings_floppy.h +++ b/src/win/win_settings_floppy.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_floppy.h 1.0.9 2018/10/24 + * Version: @(#)win_settings_floppy.h 1.0.10 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -59,7 +59,12 @@ floppy_image_list_init(HWND hwndList) ILC_MASK | ILC_COLOR32, 1, 1); for (i = 0; i < 14; i++) { - hIconItem = LoadIcon(hInstance, (LPCWSTR)ui_fdd_icon(i)); +#if (defined(_MSC_VER) && defined(_M_X64)) || \ + (defined(__GNUC__) && defined(__amd64__)) + hIconItem = LoadIcon(hInstance, (LPCWSTR)((uint64_t)ui_fdd_icon(i))); +#else + hIconItem = LoadIcon(hInstance, (LPCWSTR)((uint32_t)ui_fdd_icon(i))); +#endif ImageList_AddIcon(hSmall, hIconItem); DestroyIcon(hIconItem); } diff --git a/src/win/win_snd_gain.c b/src/win/win_snd_gain.c index 0380a99..b3d7936 100644 --- a/src/win/win_snd_gain.c +++ b/src/win/win_snd_gain.c @@ -8,7 +8,7 @@ * * Implementation of the Sound Gain dialog. * - * Version: @(#)win_snd_gain.c 1.0.9 2018/10/24 + * Version: @(#)win_snd_gain.c 1.0.10 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -105,5 +105,5 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) void dlg_sound_gain(void) { - DialogBox(plat_lang_dll(), (LPCTSTR)DLG_SND_GAIN, hwndMain, dlg_proc); + DialogBox(plat_lang_dll(), (LPCWSTR)DLG_SND_GAIN, hwndMain, dlg_proc); } diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 204fa33..201ee6d 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -8,7 +8,7 @@ * * Implement the user Interface module. * - * Version: @(#)win_ui.c 1.0.31 2018/10/24 + * Version: @(#)win_ui.c 1.0.32 2018/10/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -840,6 +840,18 @@ again: /* Set the PAUSE mode depending on the renderer. */ pc_pause(0); +#ifdef USE_MANAGER + /* + * If so requested via the command line, inform the + * application that started us of our HWND, using the + * the hWnd and unique ID the application has given + * us. + */ + if (source_hwnd) + PostMessage((HWND) (uintptr_t) source_hwnd, + WM_SEND_HWND, (WPARAM)unique_id, (LPARAM)hwndMain); +#endif + /* * Everything has been configured, and all seems to work, * so now it is time to start the main thread to do some @@ -982,6 +994,19 @@ plat_fullscreen(int on) } +/* Platform support for the PAUSE action. */ +void +plat_pause(int paused) +{ +#ifdef USE_MANAGER + /* Send the WM to a manager if needed. */ + if (source_hwnd) + PostMessage((HWND) (uintptr_t) source_hwnd, + WM_SENDSTATUS, (WPARAM)paused, (LPARAM)hwndMain); +#endif +} + + /* Grab the current keyboard state. */ int plat_kbd_state(void)