diff --git a/src/devices/video/vid_ati18800.c b/src/devices/video/vid_ati18800.c index d680175..790916b 100644 --- a/src/devices/video/vid_ati18800.c +++ b/src/devices/video/vid_ati18800.c @@ -8,7 +8,7 @@ * * ATI 18800 emulation (VGA Edge-16) * - * Version: @(#)vid_ati18800.c 1.0.10 2019/02/10 + * Version: @(#)vid_ati18800.c 1.0.11 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -49,7 +49,7 @@ #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_ati_eeprom.h" +#include "vid_ati.h" # define BIOS_ROM_PATH_WONDER L"video/ati/ati18800/vga_wonder_v3-1.02.bin" diff --git a/src/devices/video/vid_ati28800.c b/src/devices/video/vid_ati28800.c index 04c903e..e62bcbf 100644 --- a/src/devices/video/vid_ati28800.c +++ b/src/devices/video/vid_ati28800.c @@ -8,7 +8,7 @@ * * ATI 28800 emulation (VGA Charger and Korean VGA) * - * Version: @(#)vid_ati28800.c 1.0.16 2019/02/10 + * Version: @(#)vid_ati28800.c 1.0.18 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,11 +47,12 @@ #include "../../mem.h" #include "../../rom.h" #include "../../device.h" +#include "../../plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" #include "vid_sc1502x_ramdac.h" -#include "vid_ati_eeprom.h" +#include "vid_ati.h" enum { @@ -220,7 +221,7 @@ ati28800k_out(uint16_t port, uint8_t val, void *priv) dev->in_get_korean_font_kind_set = 0; if (dev->get_korean_font_enabled) { if ((dev->get_korean_font_base & 0x7F) > 0x20 && (dev->get_korean_font_base & 0x7F) < 0x7F) - fontdatksc5601_user[(dev->get_korean_font_kind & 4) * 24 + (dev->get_korean_font_base & 0x7F) - 0x20].chr[dev->get_korean_font_index] = val; + fontdatk_user[(dev->get_korean_font_kind & 4) * 24 + (dev->get_korean_font_base & 0x7F) - 0x20].chr[dev->get_korean_font_index] = val; dev->get_korean_font_index++; dev->get_korean_font_index &= 0x1F; } else { @@ -337,12 +338,12 @@ ati28800k_in(uint16_t port, void *priv) if (dev->get_korean_font_enabled) { switch(dev->get_korean_font_kind >> 8) { case 4: /* ROM font */ - ret = fontdatksc5601[dev->get_korean_font_base].chr[dev->get_korean_font_index++]; + ret = fontdatk[dev->get_korean_font_base].chr[dev->get_korean_font_index++]; break; case 2: /* User defined font */ if ((dev->get_korean_font_base & 0x7F) > 0x20 && (dev->get_korean_font_base & 0x7F) < 0x7F) - ret = fontdatksc5601_user[(dev->get_korean_font_kind & 4) * 24 + (dev->get_korean_font_base & 0x7F) - 0x20].chr[dev->get_korean_font_index]; + ret = fontdatk_user[(dev->get_korean_font_kind & 4) * 24 + (dev->get_korean_font_base & 0x7F) - 0x20].chr[dev->get_korean_font_index]; else ret = 0xff; dev->get_korean_font_index++; @@ -443,6 +444,44 @@ ati28800k_recalctimings(svga_t *svga) } +/* + * Also used by the Korean ET4000AX. + * + * This will eventually need the 'svga' pointer to store + * the font data in to, which is global data right now. + */ +int +ati28800k_load_font(svga_t *svga, const wchar_t *fn) +{ + FILE *fp; + int c, d; + + fp = plat_fopen(rom_path(fn), L"rb"); + if (fp == NULL) { + ERRLOG("ATI28800K: cannot load font '%ls'\n", fn); + return(0); + } + + if (fontdatk == NULL) + fontdatk = (dbcs_font_t *)mem_alloc(16384 * sizeof(dbcs_font_t)); + + if (fontdatk_user == NULL) { + c = 192 * sizeof(dbcs_font_t); + fontdatk_user = (dbcs_font_t *)mem_alloc(c); + memset(fontdatk_user, 0x00, c); + } + + for (c = 0; c < 16384; c++) { + for (d = 0; d < 32; d++) + fontdatk[c].chr[d] = fgetc(fp); + } + + (void)fclose(fp); + + return(1); +} + + static void * ati28800_init(const device_t *info) { @@ -494,8 +533,6 @@ ati28800_init(const device_t *info) dev->in_get_korean_font_kind_set = 0; dev->ksc5601_mode_enabled = 0; - video_load_font(FONT_ATIKOR_PATH, 6); - rom_init(&dev->bios_rom, BIOS_ATIKOR_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); ati_eeprom_load(&dev->eeprom, L"atikorvga.nvr", 0); @@ -533,6 +570,14 @@ ati28800_init(const device_t *info) dev->svga.miscout = 1; + if (info->local == VID_ATIKOREANVGA) { + if (! ati28800k_load_font(&dev->svga, FONT_ATIKOR_PATH)) { + svga_close(&dev->svga); + free(dev); + return(NULL); + } + } + video_inform(VID_TYPE_SPEC, (const video_timings_t *)info->vid_timing); diff --git a/src/devices/video/vid_ati_eeprom.c b/src/devices/video/vid_ati_eeprom.c index 5006b4a..c53f7ae 100644 --- a/src/devices/video/vid_ati_eeprom.c +++ b/src/devices/video/vid_ati_eeprom.c @@ -8,13 +8,13 @@ * * Emulation of the EEPROM on select ATI cards. * - * Version: @(#)vid_ati_eeprom.c 1.0.4 2018/09/04 + * Version: @(#)vid_ati_eeprom.c 1.0.5 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -44,215 +44,208 @@ #include "../../mem.h" #include "../../nvr.h" #include "../../plat.h" -#include "vid_ati_eeprom.h" +#include "vid_ati.h" -enum -{ - EEPROM_IDLE, - EEPROM_WAIT, - EEPROM_OPCODE, - EEPROM_INPUT, - EEPROM_OUTPUT +enum { + EEPROM_IDLE, + EEPROM_WAIT, + EEPROM_OPCODE, + EEPROM_INPUT, + EEPROM_OUTPUT }; -enum -{ - EEPROM_OP_EW = 4, - EEPROM_OP_WRITE = 5, - EEPROM_OP_READ = 6, - EEPROM_OP_ERASE = 7, +enum { + EEPROM_OP_EW = 4, + EEPROM_OP_WRITE = 5, + EEPROM_OP_READ = 6, + EEPROM_OP_ERASE = 7, - EEPROM_OP_WRALMAIN = -1 + EEPROM_OP_WRALMAIN = -1 }; -enum -{ - EEPROM_OP_EWDS = 0, - EEPROM_OP_WRAL = 1, - EEPROM_OP_ERAL = 2, - EEPROM_OP_EWEN = 3 +enum { + EEPROM_OP_EWDS = 0, + EEPROM_OP_WRAL = 1, + EEPROM_OP_ERAL = 2, + EEPROM_OP_EWEN = 3 }; -void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type) + +void +ati_eeprom_load(ati_eeprom_t *dev, wchar_t *fn, int type) { - FILE *f; + FILE *fp; - eeprom->type = type; - memset(eeprom->data, 0, eeprom->type ? 512 : 128); + dev->type = type; + memset(dev->data, 0, dev->type ? 512 : 128); - wcscpy(eeprom->fn, fn); - f = plat_fopen(nvr_path(eeprom->fn), L"rb"); - if (f != NULL) - { - (void)fread(eeprom->data, 1, eeprom->type ? 512 : 128, f); - fclose(f); - } + wcscpy(dev->fn, fn); + fp = plat_fopen(nvr_path(dev->fn), L"rb"); + if (fp != NULL) { + (void)fread(dev->data, 1, dev->type ? 512 : 128, fp); + fclose(fp); + } } -void ati_eeprom_save(ati_eeprom_t *eeprom) -{ - FILE *f = plat_fopen(nvr_path(eeprom->fn), L"wb"); - if (f != NULL) { - (void)fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f); - fclose(f); +void +ati_eeprom_save(ati_eeprom_t *dev) +{ + FILE *fp = plat_fopen(nvr_path(dev->fn), L"wb"); + + if (fp != NULL) { + (void)fwrite(dev->data, 1, dev->type ? 512 : 128, fp); + fclose(fp); + } +} + + +void +ati_eeprom_write(ati_eeprom_t *dev, int ena, int clk, int dat) +{ + int c; + + if (! ena) + dev->out = 1; + + if (clk && !dev->oldclk) { + if (ena && !dev->oldena) { + dev->state = EEPROM_WAIT; + dev->opcode = 0; + dev->count = 3; + dev->out = 1; + } else if (ena) { + switch (dev->state) { + case EEPROM_WAIT: + if (! dat) + break; + dev->state = EEPROM_OPCODE; + /*FALLTHROUGH*/ + + case EEPROM_OPCODE: + dev->opcode = (dev->opcode << 1) | (dat ? 1 : 0); + dev->count--; + if (! dev->count) { + switch (dev->opcode) { + case EEPROM_OP_WRITE: + dev->count = dev->type ? 24 : 22; + dev->state = EEPROM_INPUT; + dev->dat = 0; + break; + + case EEPROM_OP_READ: + dev->count = dev->type ? 8 : 6; + dev->state = EEPROM_INPUT; + dev->dat = 0; + break; + + case EEPROM_OP_EW: + dev->count = 2; + dev->state = EEPROM_INPUT; + dev->dat = 0; + break; + + case EEPROM_OP_ERASE: + dev->count = dev->type ? 8 : 6; + dev->state = EEPROM_INPUT; + dev->dat = 0; + break; + } + } + break; + + case EEPROM_INPUT: + dev->dat = (dev->dat << 1) | (dat ? 1 : 0); + dev->count--; + if (! dev->count) { + switch (dev->opcode) { + case EEPROM_OP_WRITE: + if (! dev->wp) { + dev->data[(dev->dat >> 16) & (dev->type ? 255 : 63)] = dev->dat & 0xffff; + ati_eeprom_save(dev); + } + dev->state = EEPROM_IDLE; + dev->out = 1; + break; + + case EEPROM_OP_READ: + dev->count = 17; + dev->state = EEPROM_OUTPUT; + dev->dat = dev->data[dev->dat]; + break; + + case EEPROM_OP_EW: + switch (dev->dat) { + case EEPROM_OP_EWDS: + dev->wp = 1; + break; + + case EEPROM_OP_WRAL: + dev->opcode = EEPROM_OP_WRALMAIN; + dev->count = 20; + break; + + case EEPROM_OP_ERAL: + if (! dev->wp) { + memset(dev->data, 0xff, 128); + ati_eeprom_save(dev); + } + break; + + case EEPROM_OP_EWEN: + dev->wp = 0; + break; + } + dev->state = EEPROM_IDLE; + dev->out = 1; + break; + + case EEPROM_OP_ERASE: + if (! dev->wp) { + dev->data[dev->dat] = 0xffff; + ati_eeprom_save(dev); + } + dev->state = EEPROM_IDLE; + dev->out = 1; + break; + + case EEPROM_OP_WRALMAIN: + if (! dev->wp) { + for (c = 0; c < 256; c++) + dev->data[c] = dev->dat; + ati_eeprom_save(dev); + } + dev->state = EEPROM_IDLE; + dev->out = 1; + break; + } + } + break; + } + } + dev->oldena = ena; + } else if (!clk && dev->oldclk) { + if (ena) { + switch (dev->state) { + case EEPROM_OUTPUT: + dev->out = (dev->dat & 0x10000) ? 1 : 0; + dev->dat <<= 1; + dev->count--; + if (! dev->count) { + dev->state = EEPROM_IDLE; + } + break; + } } + } + + dev->oldclk = clk; } -void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat) + +int +ati_eeprom_read(ati_eeprom_t *dev) { - int c; - if (!ena) - { - eeprom->out = 1; - } - if (clk && !eeprom->oldclk) - { - if (ena && !eeprom->oldena) - { - eeprom->state = EEPROM_WAIT; - eeprom->opcode = 0; - eeprom->count = 3; - eeprom->out = 1; - } - else if (ena) - { - switch (eeprom->state) - { - case EEPROM_WAIT: - if (!dat) - break; - eeprom->state = EEPROM_OPCODE; - /* fall through */ - case EEPROM_OPCODE: - eeprom->opcode = (eeprom->opcode << 1) | (dat ? 1 : 0); - eeprom->count--; - if (!eeprom->count) - { - switch (eeprom->opcode) - { - case EEPROM_OP_WRITE: - eeprom->count = eeprom->type ? 24 : 22; - eeprom->state = EEPROM_INPUT; - eeprom->dat = 0; - break; - case EEPROM_OP_READ: - eeprom->count = eeprom->type ? 8 : 6; - eeprom->state = EEPROM_INPUT; - eeprom->dat = 0; - break; - case EEPROM_OP_EW: - eeprom->count = 2; - eeprom->state = EEPROM_INPUT; - eeprom->dat = 0; - break; - case EEPROM_OP_ERASE: - eeprom->count = eeprom->type ? 8 : 6; - eeprom->state = EEPROM_INPUT; - eeprom->dat = 0; - break; - } - } - break; - - case EEPROM_INPUT: - eeprom->dat = (eeprom->dat << 1) | (dat ? 1 : 0); - eeprom->count--; - if (!eeprom->count) - { - switch (eeprom->opcode) - { - case EEPROM_OP_WRITE: - if (!eeprom->wp) - { - eeprom->data[(eeprom->dat >> 16) & (eeprom->type ? 255 : 63)] = eeprom->dat & 0xffff; - ati_eeprom_save(eeprom); - } - eeprom->state = EEPROM_IDLE; - eeprom->out = 1; - break; - - case EEPROM_OP_READ: - eeprom->count = 17; - eeprom->state = EEPROM_OUTPUT; - eeprom->dat = eeprom->data[eeprom->dat]; - break; - case EEPROM_OP_EW: - switch (eeprom->dat) - { - case EEPROM_OP_EWDS: - eeprom->wp = 1; - break; - case EEPROM_OP_WRAL: - eeprom->opcode = EEPROM_OP_WRALMAIN; - eeprom->count = 20; - break; - case EEPROM_OP_ERAL: - if (!eeprom->wp) - { - memset(eeprom->data, 0xff, 128); - ati_eeprom_save(eeprom); - } - break; - case EEPROM_OP_EWEN: - eeprom->wp = 0; - break; - } - eeprom->state = EEPROM_IDLE; - eeprom->out = 1; - break; - - case EEPROM_OP_ERASE: - if (!eeprom->wp) - { - eeprom->data[eeprom->dat] = 0xffff; - ati_eeprom_save(eeprom); - } - eeprom->state = EEPROM_IDLE; - eeprom->out = 1; - break; - - case EEPROM_OP_WRALMAIN: - if (!eeprom->wp) - { - for (c = 0; c < 256; c++) - eeprom->data[c] = eeprom->dat; - ati_eeprom_save(eeprom); - } - eeprom->state = EEPROM_IDLE; - eeprom->out = 1; - break; - } - } - break; - } - } - eeprom->oldena = ena; - } - else if (!clk && eeprom->oldclk) - { - if (ena) - { - switch (eeprom->state) - { - case EEPROM_OUTPUT: - eeprom->out = (eeprom->dat & 0x10000) ? 1 : 0; - eeprom->dat <<= 1; - eeprom->count--; - if (!eeprom->count) - { - eeprom->state = EEPROM_IDLE; - } - break; - } - } - } - eeprom->oldclk = clk; + return dev->out; } - -int ati_eeprom_read(ati_eeprom_t *eeprom) -{ - return eeprom->out; -} - diff --git a/src/devices/video/vid_ati_eeprom.h b/src/devices/video/vid_ati_eeprom.h deleted file mode 100644 index be16576..0000000 --- a/src/devices/video/vid_ati_eeprom.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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. - * - * Definitions for the ATI EEPROM driver. - * - * Version: @(#)vid_ati_eeprom.h 1.0.1 2018/02/14 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * 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. - */ -#ifndef VIDEO_ATI_EEPROM_H -# define VIDEO_ATI_EEPROM_H - - -typedef struct ati_eeprom_t -{ - uint16_t data[256]; - - int oldclk, oldena; - int opcode, state, count, out; - int wp; - uint32_t dat; - int type; - - wchar_t fn[256]; -} ati_eeprom_t; - -void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type); -void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat); -int ati_eeprom_read(ati_eeprom_t *eeprom); - - -#endif /*VIDEO_ATI_EEPROM_H*/ diff --git a/src/devices/video/vid_ati_mach64.c b/src/devices/video/vid_ati_mach64.c index e9e45d0..c58b4b8 100644 --- a/src/devices/video/vid_ati_mach64.c +++ b/src/devices/video/vid_ati_mach64.c @@ -8,13 +8,13 @@ * * ATi Mach64 graphics card emulation. * - * Version: @(#)vid_ati_mach64.c 1.0.14 2018/10/08 + * Version: @(#)vid_ati_mach64.c 1.0.15 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -51,7 +51,7 @@ #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_ati_eeprom.h" +#include "vid_ati.h" #include "vid_ati68860_ramdac.h" #include "vid_ics2595.h" diff --git a/src/devices/video/vid_cga.c b/src/devices/video/vid_cga.c index 1762259..e6613a2 100644 --- a/src/devices/video/vid_cga.c +++ b/src/devices/video/vid_cga.c @@ -8,7 +8,7 @@ * * Emulation of the old and new IBM CGA graphics cards. * - * Version: @(#)vid_cga.c 1.0.11 2019/01/01 + * Version: @(#)vid_cga.c 1.0.12 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -649,7 +649,7 @@ cga_standalone_init(const device_t *info) cga_palette = (dev->rgb_type << 1); cgapal_rebuild(); - video_load_font(CGA_FONT_ROM_PATH, (dev->font_type) ? 8 : 2); + video_load_font(CGA_FONT_ROM_PATH, (dev->font_type) ? 2 : 1); video_inform(VID_TYPE_CGA, info->vid_timing); diff --git a/src/devices/video/vid_et4000.c b/src/devices/video/vid_et4000.c index e6182ba..ad80a61 100644 --- a/src/devices/video/vid_et4000.c +++ b/src/devices/video/vid_et4000.c @@ -8,14 +8,14 @@ * * Emulation of the Tseng Labs ET4000. * - * Version: @(#)vid_et4000.c 1.0.13 2018/10/08 + * Version: @(#)vid_et4000.c 1.0.14 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, * GreatPsycho, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -51,6 +51,7 @@ #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" +#include "vid_ati.h" /* for the font loader */ #include "vid_sc1502x_ramdac.h" @@ -155,7 +156,7 @@ et4000k_in(uint16_t addr, void *priv) switch(dev->get_korean_font_enabled) { case 3: if ((dev->port_32cb_val & 0x30) == 0x30) { - val = fontdatksc5601[dev->get_korean_font_base].chr[dev->get_korean_font_index++]; + val = fontdatk[dev->get_korean_font_base].chr[dev->get_korean_font_index++]; dev->get_korean_font_index &= 0x1f; } else if ((dev->port_32cb_val & 0x30) == 0x20 && @@ -164,18 +165,18 @@ et4000k_in(uint16_t addr, void *priv) switch(dev->get_korean_font_base & 0x3f80) { case 0x2480: if (dev->get_korean_font_index < 16) - val = fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index]; + val = fontdatk_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index]; else if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) - val = fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8]; + val = fontdatk_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8]; break; case 0x3f00: if (dev->get_korean_font_index < 16) - val = fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index]; + val = fontdatk_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index]; else if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) - val = fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8]; + val = fontdatk_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8]; break; default: @@ -358,18 +359,18 @@ et4000k_out(uint16_t addr, uint8_t val, void *priv) switch (dev->get_korean_font_base & 0x3f80) { case 0x2480: if (dev->get_korean_font_index < 16) - fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index] = val; + fontdatk_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index] = val; else if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) - fontdatksc5601_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8] = val; + fontdatk_user[(dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8] = val; break; case 0x3f00: if (dev->get_korean_font_index < 16) - fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index] = val; + fontdatk_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index] = val; else if (dev->get_korean_font_index >= 24 && dev->get_korean_font_index < 40) - fontdatksc5601_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8] = val; + fontdatk_user[96 + (dev->get_korean_font_base & 0x7f) - 0x20].chr[dev->get_korean_font_index - 8] = val; break; default: @@ -487,9 +488,11 @@ et4000_init(const device_t *info) switch(dev->type) { case 0: /* ISA ET4000AX */ dev->vram_size = device_get_config_int("memory") << 10; + svga_init(&dev->svga, dev, dev->vram_size, et4000_recalctimings, et4000_in, et4000_out, NULL, NULL); + io_sethandler(0x03c0, 32, et4000_in,NULL,NULL, et4000_out,NULL,NULL, dev); break; @@ -497,11 +500,14 @@ et4000_init(const device_t *info) case 1: /* MCA ET4000AX */ dev->is_mca = 1; dev->vram_size = 1024 << 10; + svga_init(&dev->svga, dev, dev->vram_size, et4000_recalctimings, et4000_in, et4000_out, NULL, NULL); + io_sethandler(0x03c0, 32, et4000_in,NULL,NULL, et4000_out,NULL,NULL, dev); + dev->pos_regs[0] = 0xf2; /* ET4000 MCA board ID */ dev->pos_regs[1] = 0x80; mca_add(et4000_mca_read, et4000_mca_write, dev); @@ -513,9 +519,17 @@ et4000_init(const device_t *info) dev->port_22cb_val = 0x60; dev->port_32cb_val = 0; dev->svga.ksc5601_sbyte_mask = 0x80; + svga_init(&dev->svga, dev, dev->vram_size, et4000_recalctimings, et4000k_in, et4000k_out, NULL, NULL); + + if (! ati28800k_load_font(&dev->svga, KOREAN_FONT_ROM_PATH)) { + svga_close(&dev->svga); + free(dev); + return(NULL); + } + io_sethandler(0x03c0, 32, et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); io_sethandler(0x22cb, 1, @@ -524,7 +538,6 @@ et4000_init(const device_t *info) et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); io_sethandler(0x32cb, 1, et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); - video_load_font(KOREAN_FONT_ROM_PATH, 6); fn = KOREAN_BIOS_ROM_PATH; break; } @@ -536,7 +549,7 @@ et4000_init(const device_t *info) rom_init(&dev->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - DEBUG("VIDEO: %s (vram=%dKB)\n", dev->name, dev->vram_size>>10); + DEBUG("VIDEO: %s (vram=%iKB)\n", dev->name, dev->vram_size>>10); video_inform(VID_TYPE_SPEC, (const video_timings_t *)info->vid_timing); diff --git a/src/devices/video/vid_genius.c b/src/devices/video/vid_genius.c index 5f03270..4aef9d4 100644 --- a/src/devices/video/vid_genius.c +++ b/src/devices/video/vid_genius.c @@ -63,13 +63,13 @@ * reducing the height of characters so they fit in an 8x12 cell * if necessary. * - * Version: @(#)vid_genius.c 1.0.8 2018/10/24 + * Version: @(#)vid_genius.c 1.0.9 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, * John Elliott, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2016-2018 John Elliott. * @@ -107,7 +107,7 @@ #include "video.h" -#define BIOS_ROM_PATH L"video/mdsi/genius/8x12.bin" +#define FONT_ROM_PATH L"video/mdsi/genius/8x12.bin" #define GENIUS_XSIZE 728 @@ -115,6 +115,8 @@ typedef struct { + const char *name; + mem_map_t mapping; uint8_t mda_crtc[32]; /* The 'CRTC' as the host PC sees it */ @@ -154,6 +156,8 @@ typedef struct { int cols[256][2][2]; + uint8_t fontdat[256][16]; + uint8_t *vram; } genius_t; @@ -369,7 +373,7 @@ text_line(genius_t *dev, uint8_t background) } } else { /* Draw 8 pixels of character */ - bitmap[0] = fontdat8x12[chr][sc]; + bitmap[0] = dev->fontdat[chr][sc]; for (c = 0; c < 8; c++) { col = dev->cols[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; if (!(dev->enabled) || !(dev->mda_ctrl & 8)) @@ -559,6 +563,27 @@ genius_poll(void *priv) } +static int +load_font(genius_t *dev, const wchar_t *s) +{ + FILE *fp; + int c; + + fp = plat_fopen(rom_path(s), L"rb"); + if (fp == NULL) { + ERRLOG("%s: cannot load font '%ls'\n", dev->name, s); + return(0); + } + + for (c = 0; c < 256; c++) + (void)fread(&dev->fontdat[c][0], 1, 16, fp); + + (void)fclose(fp); + + return(1); +} + + static void * genius_init(const device_t *info) { @@ -567,12 +592,16 @@ genius_init(const device_t *info) dev = (genius_t *)mem_alloc(sizeof(genius_t)); memset(dev, 0x00, sizeof(genius_t)); + dev->name = info->name; + + if (! load_font(dev, FONT_ROM_PATH)) { + free(dev); + return(NULL); + } /* 160k video RAM */ dev->vram = (uint8_t *)mem_alloc(0x28000); - video_load_font(BIOS_ROM_PATH, 4); - timer_add(genius_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in @@ -645,7 +674,7 @@ genius_close(void *priv) static int genius_available(void) { - return rom_present(BIOS_ROM_PATH); + return rom_present(FONT_ROM_PATH); } diff --git a/src/devices/video/vid_im1024.c b/src/devices/video/vid_im1024.c index 1513167..0597121 100644 --- a/src/devices/video/vid_im1024.c +++ b/src/devices/video/vid_im1024.c @@ -38,7 +38,7 @@ * This is implemented by holding a FIFO of unlimited depth in * the IM1024 to receive the data. * - * Version: @(#)vid_im1024.c 1.0.2 2019/03/02 + * Version: @(#)vid_im1024.c 1.0.3 2019/03/03 * * Authors: Fred N. van Kempen, * John Elliott, @@ -99,16 +99,14 @@ typedef struct { static void fifo_write(im1024_t *dev, uint8_t val) { -#if 0 - DEBUG(("IM1024: fifo_write: %02x [rd=%04x wr=%04x]\n", - val, dev->fifo_rdptr, dev->fifo_wrptr)); -#endif + DBGLOG(1, "IM1024: fifo_write: %02x [rd=%04x wr=%04x]\n", + val, dev->fifo_rdptr, dev->fifo_wrptr); if (((dev->fifo_wrptr + 1) % dev->fifo_len) == dev->fifo_rdptr) { /* FIFO is full. Double its size. */ uint8_t *buf; - DEBUG("IM1024: fifo_resize: %i to %i\n", + DBGLOG(1, "IM1024: fifo_resize: %i to %i\n", dev->fifo_len, 2 * dev->fifo_len); buf = realloc(dev->fifo, 2 * dev->fifo_len); @@ -121,10 +119,10 @@ fifo_write(im1024_t *dev, uint8_t val) dev->fifo_len *= 2; } - /* Append to the queue */ + /* Append to the queue. */ dev->fifo[dev->fifo_wrptr++] = val; - /* Wrap if end of buffer reached */ + /* Wrap if end of buffer reached. */ if (dev->fifo_wrptr >= dev->fifo_len) dev->fifo_wrptr = 0; } @@ -148,15 +146,18 @@ fifo_read(im1024_t *dev) } -/* Where a normal PGC would just read from the ring buffer at 0xC6300, the - * IM-1024 can read either from this or from its internal FIFO. The internal - * FIFO has priority. */ +/* + * Where a normal PGC would just read from the ring buffer at 0xC6300, + * the IM-1024 can read from either this or from its internal FIFO. + * + * The internal FIFO has priority. + */ static int input_byte(pgc_t *pgc, uint8_t *result) { im1024_t *dev = (im1024_t *)pgc; - /* If input buffer empty, wait for it to fill */ + /* If input buffer empty, wait for it to fill. */ while ((dev->fifo_wrptr == dev->fifo_rdptr) && (pgc->mapram[0x300] == pgc->mapram[0x301])) { pgc->waiting_input_fifo = 1; @@ -179,7 +180,7 @@ input_byte(pgc_t *pgc, uint8_t *result) } -/* Macros to disable clipping and save clip state */ +/* Macros to disable clipping and save clip state. */ #define PUSHCLIP { \ uint16_t vp_x1, vp_x2, vp_y1, vp_y2; \ vp_x1 = pgc->vp_x1; \ @@ -206,7 +207,7 @@ im1024_read(uint32_t addr, void *priv) { im1024_t *dev = (im1024_t *)priv; - if (addr == 0xC6331 && dev->pgc.mapram[0x330] == 1) { + if (addr == 0xc6331 && dev->pgc.mapram[0x330] == 1) { /* Hardcode that there are 128 bytes free. */ return(0x80); } @@ -221,9 +222,11 @@ im1024_write(uint32_t addr, uint8_t val, void *priv) { im1024_t *dev = (im1024_t *)priv; - /* If we are in 'fast' input mode, send all writes to the internal - * FIFO */ - if (addr >= 0xC6000 && addr < 0xC6100 && dev->pgc.mapram[0x330] == 1) { + /* + * If we are in 'fast' input mode, send all + * writes to the internal FIFO. + */ + if (addr >= 0xc6000 && addr < 0xc6100 && dev->pgc.mapram[0x330] == 1) { fifo_write(dev, val); DBGLOG(1, "IM1024: write(%02x)\n", val); @@ -239,8 +242,10 @@ im1024_write(uint32_t addr, uint8_t val, void *priv) } -/* I don't know what the IMGSIZ command does, only that the Windows driver - * issues it. So just parse and ignore it */ +/* + * I don't know what the IMGSIZ command does, only that the + * Windows driver issues it. So just parse and ignore it. + */ static void hndl_imgsiz(pgc_t *pgc) { @@ -259,8 +264,10 @@ hndl_imgsiz(pgc_t *pgc) } -/* I don't know what the IPREC command does, only that the Windows driver - * issues it. So just parse and ignore it */ +/* + * I don't know what the IPREC command does, only that the + * Windows driver issues it. So just parse and ignore it. + */ static void hndl_iprec(pgc_t *pgc) { @@ -298,8 +305,10 @@ hndl_linfun(pgc_t *pgc) } -/* I think PAN controls which part of the 1024x1024 framebuffer is displayed - * in the 1024x800 visible screen. */ +/* + * I think PAN controls which part of the 1024x1024 framebuffer + * is displayed in the 1024x800 visible screen. + */ static void hndl_pan(pgc_t *pgc) { @@ -315,7 +324,7 @@ hndl_pan(pgc_t *pgc) } -/* PLINE draws a non-filled polyline at a fixed position */ +/* PLINE draws a non-filled polyline at a fixed position. */ static void hndl_pline(pgc_t *pgc) { @@ -340,9 +349,12 @@ hndl_pline(pgc_t *pgc) } -/* Blit a single row of pixels from one location to another. To avoid - * difficulties if the two overlap, read both rows into memory, process them - * there, and write the result back. */ +/* + * Blit a single row of pixels from one location to another. + * + * To avoid difficulties if the two overlap, read both rows + * into memory, process them there, and write the result back. + */ static void blkmov_row(pgc_t *pgc, int16_t x0, int16_t x1, int16_t x2, int16_t sy, int16_t ty) { @@ -355,37 +367,35 @@ blkmov_row(pgc_t *pgc, int16_t x0, int16_t x1, int16_t x2, int16_t sy, int16_t t dst[x - x0] = pgc_read_pixel(pgc, x - x0 + x2, ty); } - for (x = x0; x <= x1; x++) { - switch (pgc->draw_mode) { - default: - case 0: - pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0]); - break; + for (x = x0; x <= x1; x++) switch (pgc->draw_mode) { + default: + case 0: + pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0]); + break; - case 1: - pgc_write_pixel(pgc, (x - x0 + x2), ty, dst[x - x0] ^ 0xFF); - break; + case 1: + pgc_write_pixel(pgc, (x - x0 + x2), ty, dst[x - x0] ^ 0xff); + break; - case 2: - pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] ^ dst[x - x0]); - break; + case 2: + pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] ^ dst[x - x0]); + break; - case 3: - pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] & dst[x - x0]); - break; - } + case 3: + pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] & dst[x - x0]); + break; } } -/* BLKMOV blits a rectangular area from one location to another, with no - * clipping. */ +/* + * BLKMOV blits a rectangular area from one location to another. + * + * Clipping is disabled. + */ static void hndl_blkmov(pgc_t *pgc) { -#if 0 - im1024_t *dev = (im1024_t *)pgc; -#endif int16_t x0, y0; int16_t x1, y1; int16_t x2, y2; @@ -398,13 +408,15 @@ hndl_blkmov(pgc_t *pgc) if (! pgc_param_word(pgc, &x2)) return; if (! pgc_param_word(pgc, &y2)) return; - DEBUG("IM1024: BLKMOV %i,%i,%i,%i,%i,%i\n", x0, y0, x1, y1, x2, y2); + DEBUG("IM1024: BLKMOV %i,%i,%i,%i,%i,%i\n", x0,y0,x1,y1,x2,y2); /* Disable clipping. */ PUSHCLIP - /* Either go down from the top, or up from the bottom, depending - * whether areas might overlap */ + /* + * Either go down from the top, or up from the bottom, + * depending whether areas might overlap. + */ if (y2 <= y0) { for (y = y0; y <= y1; y++) blkmov_row(pgc, x0, x1, x2, y, y - y0 + y2); @@ -418,8 +430,10 @@ hndl_blkmov(pgc_t *pgc) } -/* This overrides the PGC ELIPSE command to parse its parameters as words - * rather than coordinates */ +/* + * Override the PGC ELIPSE command to parse its + * parameters as words rather than coordinates. + */ static void hndl_ellipse(pgc_t *pgc) { @@ -435,8 +449,10 @@ hndl_ellipse(pgc_t *pgc) } -/* This overrides the PGC MOVE command to parse its parameters as words - * rather than coordinates */ +/* + * Override the PGC MOVE command to parse its + * parameters as words rather than coordinates. + */ static void hndl_move(pgc_t *pgc) { @@ -445,15 +461,17 @@ hndl_move(pgc_t *pgc) if (! pgc_param_word(pgc, &x)) return; if (! pgc_param_word(pgc, &y)) return; + DEBUG("IM1024: MOVE %i,%i\n", x, y); + pgc->x = x << 16; pgc->y = y << 16; - - DEBUG("IM1024: MOVE %i,%i\n", x, y); } -/* This overrides the PGC DRAW command to parse its parameters as words - * rather than coordinates */ +/* + * Override the PGC DRAW command to parse its + * parameters as words rather than coordinates. + */ static void hndl_draw(pgc_t *pgc) { @@ -465,13 +483,16 @@ hndl_draw(pgc_t *pgc) DEBUG("IM1024: DRAW %i,%i to %i,%i\n", pgc->x >> 16, pgc->y >> 16, x, y); pgc_draw_line(pgc, pgc->x, pgc->y, x << 16, y << 16, pgc->line_pattern); + pgc->x = x << 16; pgc->y = y << 16; } -/* This overrides the PGC POLY command to parse its parameters as words - * rather than coordinates */ +/* + * Override the PGC POLY command to parse its + * parameters as words rather than coordinates. + */ static void hndl_poly(pgc_t *pgc) { @@ -484,7 +505,6 @@ hndl_poly(pgc_t *pgc) x = (int32_t *)mem_alloc(as * sizeof(int32_t)); y = (int32_t *)mem_alloc(as * sizeof(int32_t)); - if (!x || !y) { DEBUG("IM1024: POLY: out of memory\n"); return; @@ -519,9 +539,11 @@ hndl_poly(pgc_t *pgc) realcount++; } - /* If we are in a command list, peek ahead to see if the next + /* + * If we are in a command list, peek ahead to see if the next * command is also POLY. If so, that's a continuation of this - * polygon! */ + * polygon! + */ parsing = 0; if (pgc->clcur && (pgc->clcur->rdptr+1) < pgc->clcur->wrptr && pgc->clcur->list[pgc->clcur->rdptr] == 0x30) { @@ -573,8 +595,10 @@ parse_poly(pgc_t *pgc, pgc_cl_t *cl, int c) } -/* This overrides the PGC RECT command to parse its parameters as words - * rather than coordinates */ +/* + * Override the PGC RECT command to parse its + * parameters as words rather than coordinates. + */ static void hndl_rect(pgc_t *pgc) { @@ -586,7 +610,7 @@ hndl_rect(pgc_t *pgc) if (! pgc_param_word(pgc, &x1)) return; if (! pgc_param_word(pgc, &y1)) return; - /* Convert to raster coords */ + /* Convert to raster coords. */ pgc_sto_raster(pgc, &x0, &y0); pgc_sto_raster(pgc, &x1, &y1); @@ -608,8 +632,13 @@ hndl_rect(pgc_t *pgc) } -/* TODO: Text drawing should probably be implemented in vid_pgc.c rather - * than vid_im1024.c */ +/* + * FIXME: + * Define a font character. + * + * Text drawing should probably be implemented in + * vid_pgc.c rather than here.. + */ static void hndl_tdefin(pgc_t *pgc) { @@ -619,8 +648,8 @@ hndl_tdefin(pgc_t *pgc) unsigned len, n; if (! pgc_param_byte(pgc, &ch)) return; - if (! pgc_param_byte(pgc, &rows)) return; if (! pgc_param_byte(pgc, &cols)) return; + if (! pgc_param_byte(pgc, &rows)) return; DEBUG("IM1024: TDEFIN (%i,%i,%i) 0x%02x 0x%02x\n", ch, rows, cols, pgc->mapram[0x300], pgc->mapram[0x301]); @@ -633,15 +662,27 @@ hndl_tdefin(pgc_t *pgc) dev->font[ch][n] = bt; } - dev->fontx[ch] = rows; - dev->fonty[ch] = cols; + dev->fontx[ch] = cols; + dev->fonty[ch] = rows; +} + + +static void +hndl_tsize(pgc_t *pgc) +{ + int16_t size; + + if (!pgc_param_word(pgc, &size)) return; + DEBUG("IM1024: TSIZE(%i)\n", size); + + pgc->tsize = size << 16; } static void hndl_twrite(pgc_t *pgc) { - uint8_t buf[256], rbuf[256]; + uint8_t buf[256]; im1024_t *dev = (im1024_t *)pgc; uint8_t count, mask, *row; int x, y, wb, n; @@ -652,30 +693,21 @@ hndl_twrite(pgc_t *pgc) for (n = 0; n < count; n++) if (! pgc_param_byte(pgc, &buf[n])) return; - buf[count] = 0; - for (n = 0; n <= count; n++) { - if (isprint(buf[n]) || 0 == buf[n]) - rbuf[n] = buf[n]; - else - rbuf[n] = '?'; - } pgc_sto_raster(pgc, &x0, &y0); - DEBUG("IM1024: TWRITE (%i,%-*.*s) x0=%i y0=%i\n", - count, count, count, rbuf, x0, y0); + DEBUG("IM1024: TWRITE (%i) x0=%i y0=%i\n", count, x0, y0); for (n = 0; n < count; n++) { wb = (dev->fontx[buf[n]] + 7) / 8; - DEBUG("IM1024: ch=0x%02x w=%d h=%i wb=%i\n", + DEBUG("IM1024: ch=0x%02x w=%i h=%i wb=%i\n", buf[n], dev->fontx[buf[n]], dev->fonty[buf[n]], wb); for (y = 0; y < dev->fonty[buf[n]]; y++) { mask = 0x80; row = &dev->font[buf[n]][y * wb]; for (x = 0; x < dev->fontx[buf[n]]; x++) { - rbuf[x] = (row[0] & mask) ? '#' : '-'; if (row[0] & mask) pgc_plot(pgc, x + x0, y0 - y); mask = mask >> 1; @@ -684,8 +716,50 @@ hndl_twrite(pgc_t *pgc) row++; } } - rbuf[x++] = '\n'; - rbuf[x++] = 0; + } + + x0 += dev->fontx[buf[n]]; + } +} + + +static void +hndl_txt88(pgc_t *pgc) +{ + uint8_t buf[256]; + im1024_t *dev = (im1024_t *)pgc; + uint8_t count, mask, *row; + int16_t x0 = pgc->x >> 16; + int16_t y0 = pgc->y >> 16; + unsigned n; + int x, y, wb; + + if (! pgc_param_byte(pgc, &count)) return; + + for (n = 0; n < count; n++) + if (! pgc_param_byte(pgc, &buf[n])) return; + buf[count] = 0; + + pgc_sto_raster(pgc, &x0, &y0); + + DEBUG("IM204: TWRITE (%i) x0=%i y0=%i\n", count, x0, y0); + + for (n = 0; n < count; n++) { + wb = (dev->fontx[buf[n]] + 7) / 8; + DEBUG("IM1024: ch=0x%02x w=%i h=%i wb=%i\n", + buf[n], dev->fontx[buf[n]], dev->fonty[buf[n]], wb); + + for (y = 0; y < dev->fonty[buf[n]]; y++) { + mask = 0x80; + row = &dev->font[buf[n]][y * wb]; + for (x = 0; x < dev->fontx[buf[n]]; x++) { + if (row[0] & mask) pgc_plot(pgc, x + x0, y0 - y); + mask = mask >> 1; + if (mask == 0) { + mask = 0x80; + row++; + } + } } x0 += dev->fontx[buf[n]]; @@ -704,8 +778,7 @@ hndl_imagew(pgc_t *pgc) if (! pgc_param_word(pgc, &col1)) return; if (! pgc_param_word(pgc, &col2)) return; - /* IMAGEW already uses raster coordinates so there is no need to - * convert it */ + /* Already using raster coordinates, no need to convert. */ DEBUG("IM1024: IMAGEW (row=%i,col1=%i,col2=%i)\n", row1, col1, col2); vp_x1 = pgc->vp_x1; @@ -728,34 +801,32 @@ hndl_imagew(pgc_t *pgc) pgc_write_pixel(pgc, col1, row1, v1); col1++; } + } else { + /* In hex mode, it's RLE compressed. */ + while (col1 <= col2) { + if (! pgc_param_byte(pgc, &v1)) return; - return; - } - - /* In hex mode, it's RLE compressed. */ - while (col1 <= col2) { - if (! pgc_param_byte(pgc, &v1)) return; - - if (v1 & 0x80) { - /* Literal run. */ - v1 -= 0x7f; - while (col1 <= col2 && v1 != 0) { + if (v1 & 0x80) { + /* Literal run. */ + v1 -= 0x7f; + while (col1 <= col2 && v1 != 0) { + if (! pgc_param_byte(pgc, &v2)) return; + pgc_write_pixel(pgc, col1, row1, v2); + col1++; + v1--; + } + } else { + /* Repeated run. */ if (! pgc_param_byte(pgc, &v2)) return; - pgc_write_pixel(pgc, col1, row1, v2); - col1++; - v1--; - } - } else { - /* Repeated run. */ - if (! pgc_param_byte(pgc, &v2)) return; - v1++; - while (col1 <= col2 && v1 != 0) { - pgc_write_pixel(pgc, col1, row1, v2); - col1++; - v1--; - } - } + v1++; + while (col1 <= col2 && v1 != 0) { + pgc_write_pixel(pgc, col1, row1, v2); + col1++; + v1--; + } + } + } } /* Restore clipping. */ @@ -774,7 +845,8 @@ hndl_imagew(pgc_t *pgc) static void hndl_dot(pgc_t *pgc) { - int16_t x = pgc->x >> 16, y = pgc->y >> 16; + int16_t x = pgc->x >> 16, + y = pgc->y >> 16; pgc_sto_raster(pgc, &x, &y); @@ -785,10 +857,12 @@ hndl_dot(pgc_t *pgc) } -/* This command (which I have called IMAGEX, since I don't know its real +/* + * This command (which I have called IMAGEX, since I don't know its real * name) is a screen-to-memory blit. It reads a rectangle of bytes, rather * than the single row read by IMAGER, and does not attempt to compress - * the result */ + * the result. + */ static void hndl_imagex(pgc_t *pgc) { @@ -800,7 +874,7 @@ hndl_imagex(pgc_t *pgc) if (! pgc_param_word(pgc, &x1)) return; if (! pgc_param_word(pgc, &y1)) return; - /* IMAGEX already uses raster coordinates so don't convert */ + /* Already using raster coordinates, no need to convert. */ DEBUG("IM1024: IMAGEX (%i,%i,%i,%i)\n", x0,y0,x1,y1); for (p = y0; p <= y1; p++) { @@ -812,7 +886,8 @@ hndl_imagex(pgc_t *pgc) } -/* Commands implemented by the IM-1024. +/* + * Commands implemented by the IM-1024. * * TODO: A lot of commands need commandlist parsers. * TODO: The IM-1024 has a lot more commands that are not included here @@ -827,19 +902,22 @@ static const pgc_cmd_t im1024_commands[] = { { "ELIPSE", 0x39, hndl_ellipse, pgc_parse_words, 2 }, { "EL", 0x39, hndl_ellipse, pgc_parse_words, 2 }, { "IMAGEW", 0xd9, hndl_imagew, NULL, 0 }, - { "IW", 0xd9, hndl_imagew, NULL, 0 }, { "IMAGEX", 0xda, hndl_imagex, NULL, 0 }, - { "TWRITE", 0x8b, hndl_twrite, NULL, 0 }, - { "TDEFIN", 0x84, hndl_tdefin, NULL, 0 }, - { "TD", 0x84, hndl_tdefin, NULL, 0 }, - { "IPREC", 0xe4, hndl_iprec, NULL, 0 }, { "IMGSIZ", 0x4e, hndl_imgsiz, NULL, 0 }, - { "LUT8", 0xe6, pgc_hndl_lut8, NULL, 0 }, + { "IPREC", 0xe4, hndl_iprec, NULL, 0 }, + { "IW", 0xd9, hndl_imagew, NULL, 0 }, { "L8", 0xe6, pgc_hndl_lut8, NULL, 0 }, - { "LINFUN", 0xeb, hndl_linfun, pgc_parse_bytes, 1 }, { "LF", 0xeb, hndl_linfun, pgc_parse_bytes, 1 }, + { "LINFUN", 0xeb, hndl_linfun, pgc_parse_bytes, 1 }, + { "LUT8", 0xe6, pgc_hndl_lut8, NULL, 0 }, { "LUT8RD", 0x53, pgc_hndl_lut8rd,NULL, 0 }, { "L8RD", 0x53, pgc_hndl_lut8rd,NULL, 0 }, + { "TDEFIN", 0x84, hndl_tdefin, NULL, 0 }, + { "TD", 0x84, hndl_tdefin, NULL, 0 }, + { "TSIZE", 0x81, hndl_tsize, NULL, 0 }, + { "TS", 0x81, hndl_tsize, NULL, 0 }, + { "TWRITE", 0x8b, hndl_twrite, NULL, 0 }, + { "TXT88", 0x88, hndl_txt88, NULL, 0 }, { "PAN", 0xb7, hndl_pan, NULL, 0 }, { "POLY", 0x30, hndl_poly, parse_poly, 0 }, { "P", 0x30, hndl_poly, parse_poly, 0 }, @@ -861,8 +939,8 @@ im1024_init(const device_t *info) dev = (im1024_t *)mem_alloc(sizeof(im1024_t)); memset(dev, 0x00, sizeof(im1024_t)); - dev->fifo = (uint8_t *)mem_alloc(4096); dev->fifo_len = 4096; + dev->fifo = (uint8_t *)mem_alloc(dev->fifo_len); dev->fifo_wrptr = 0; dev->fifo_rdptr = 0; diff --git a/src/devices/video/vid_pgc.c b/src/devices/video/vid_pgc.c index 9bc0a88..5e7a4a6 100644 --- a/src/devices/video/vid_pgc.c +++ b/src/devices/video/vid_pgc.c @@ -31,8 +31,7 @@ * instructions left there for it. We simulate this behavior * with a separate thread. * - * **NOTE** This driver does not yet work, pending (proper) conversion - * to the video backend, which is different from PCem's: + * **NOTE** This driver is not finished yet: * * - cursor will blink at very high speed if used on a machine * with clock greater than 4.77MHz. We should "scale down" @@ -43,10 +42,9 @@ * * - test it with the Windows 1.x driver? * - * Until these are fixed, both the PGC as well as the IM1024 - * will remain in DevBranch mode. + * This is expected to be done shortly. * - * Version: @(#)vid_pgc.c 1.0.2 2019/03/02 + * Version: @(#)vid_pgc.c 1.0.2 2019/03/03 * * Authors: Fred N. van Kempen, * John Elliott, @@ -357,7 +355,7 @@ static void hndl_clbeg(pgc_t *dev) { const pgc_cmd_t *cmd; - uint8_t param; + uint8_t param = 0; pgc_cl_t cl; if (! pgc_param_byte(dev, ¶m)) return; @@ -409,7 +407,7 @@ static void hndl_clrun(pgc_t *dev) { pgc_cl_t *clprev = dev->clcur; - uint8_t param; + uint8_t param = 0; if (! pgc_param_byte(dev, ¶m)) return; @@ -425,8 +423,8 @@ static void hndl_cloop(pgc_t *dev) { pgc_cl_t *clprev = dev->clcur; - uint8_t param; - int16_t repeat; + uint8_t param = 0; + int16_t repeat = 0; if (! pgc_param_byte(dev, ¶m)) return; if (! pgc_param_word(dev, &repeat)) return; @@ -442,7 +440,7 @@ hndl_cloop(pgc_t *dev) static void hndl_clread(pgc_t *dev) { - uint8_t param; + uint8_t param = 0; uint32_t n; if (! pgc_param_byte(dev, ¶m)) return; @@ -458,7 +456,7 @@ hndl_clread(pgc_t *dev) static void hndl_cldel(pgc_t *dev) { - uint8_t param; + uint8_t param = 0; if (! pgc_param_byte(dev, ¶m)) return; @@ -470,7 +468,7 @@ hndl_cldel(pgc_t *dev) static void hndl_clears(pgc_t *dev) { - uint8_t param; + uint8_t param = 0; uint32_t y; if (! pgc_param_byte(dev, ¶m)) return; @@ -484,7 +482,7 @@ hndl_clears(pgc_t *dev) static void hndl_color(pgc_t *dev) { - uint8_t param; + uint8_t param = 0; if (! pgc_param_byte(dev, ¶m)) return; @@ -502,7 +500,7 @@ hndl_color(pgc_t *dev) static void hndl_linfun(pgc_t *dev) { - uint8_t param; + uint8_t param = 0; if (! pgc_param_byte(dev, ¶m)) return; @@ -518,7 +516,7 @@ hndl_linfun(pgc_t *dev) static void hndl_linpat(pgc_t *dev) { - uint16_t param; + uint16_t param = 0; if (! pgc_param_word(dev, (int16_t *)¶m)) return; @@ -531,7 +529,7 @@ hndl_linpat(pgc_t *dev) static void hndl_prmfil(pgc_t *dev) { - uint8_t param; + uint8_t param = 0; if (! pgc_param_byte(dev, ¶m)) return; @@ -547,7 +545,7 @@ hndl_prmfil(pgc_t *dev) static void hndl_move(pgc_t *dev) { - int32_t x, y; + int32_t x = 0, y = 0; if (! pgc_param_coord(dev, &x)) return; if (! pgc_param_coord(dev, &y)) return; @@ -563,7 +561,7 @@ hndl_move(pgc_t *dev) static void hndl_move3(pgc_t *dev) { - int32_t x, y, z; + int32_t x = 0, y = 0, z = 0; if (! pgc_param_coord(dev, &x)) return; if (! pgc_param_coord(dev, &y)) return; @@ -579,7 +577,7 @@ hndl_move3(pgc_t *dev) static void hndl_mover(pgc_t *dev) { - int32_t x, y; + int32_t x = 0, y = 0; if (! pgc_param_coord(dev, &x)) return; if (! pgc_param_coord(dev, &y)) return; @@ -593,7 +591,7 @@ hndl_mover(pgc_t *dev) static void hndl_mover3(pgc_t *dev) { - int32_t x, y, z; + int32_t x = 0, y = 0, z = 0; if (! pgc_param_coord(dev, &x)) return; if (! pgc_param_coord(dev, &y)) return; @@ -952,7 +950,7 @@ pgc_draw_ellipse(pgc_t *dev, int32_t x, int32_t y) static void hndl_ellipse(pgc_t *dev) { - int32_t x, y; + int32_t x = 0, y = 0; if (! pgc_param_coord(dev, &x)) return; if (! pgc_param_coord(dev, &y)) return; @@ -1008,6 +1006,8 @@ hndl_display(pgc_t *dev) if (! pgc_param_byte(dev, ¶m)) return; + DEBUG("PGC: DISPLAY(%i)\n", param); + if (param > 1) pgc_error(dev, PGC_ERROR_RANGE); else @@ -1253,6 +1253,19 @@ hndl_tjust(pgc_t *dev) } +/* TSIZE controls text horizontal spacing. */ +static void +hndl_tsize(pgc_t *pgc) +{ + int32_t param; + + if (! pgc_param_coord(pgc, ¶m)) return; + + DEBUG("PGC: TSIZE %i\n", param); + pgc->tsize = param; +} + + /* * VWPORT sets up the viewport (roughly, the clip rectangle) in * raster coordinates, measured from the bottom left of the screen. @@ -1369,6 +1382,8 @@ static const pgc_cmd_t pgc_commands[] = { { "RF", 0x04, hndl_resetf, NULL, 0 }, { "TJUST", 0x85, hndl_tjust, pgc_parse_bytes, 2 }, { "TJ", 0x85, hndl_tjust, pgc_parse_bytes, 2 }, + { "TSIZE", 0x81, hndl_tsize, pgc_parse_coords, 1 }, + { "TS", 0x81, hndl_tsize, pgc_parse_coords, 1 }, { "VWPORT", 0xb2, hndl_vwport, pgc_parse_words, 4 }, { "VWP", 0xb2, hndl_vwport, pgc_parse_words, 4 }, { "WINDOW", 0xb3, hndl_window, pgc_parse_words, 4 }, @@ -1508,6 +1523,8 @@ pgc_reset(pgc_t *dev) /* The 'CGA disable' jumper is not currently implemented. */ dev->mapram[0x30b] = dev->cga_enabled = 1; + dev->mapram[0x30c] = dev->cga_enabled; + dev->mapram[0x30d] = dev->cga_enabled; dev->mapram[0x3f8] = 0x03; /* minor version */ dev->mapram[0x3f9] = 0x01; /* minor version */ @@ -1556,6 +1573,9 @@ pgc_reset(pgc_t *dev) void pgc_setdisplay(pgc_t *dev, int cga) { + DEBUG("PGC: setdisplay(%i): cga_selected=%i cga_enabled=%i\n", + cga, dev->cga_selected, dev->cga_enabled); + if (dev->cga_selected != (dev->cga_enabled && cga)) { dev->cga_selected = (dev->cga_enabled && cga); @@ -1626,7 +1646,10 @@ pgc_clist_byte(pgc_t *dev, uint8_t *val) { if (dev->clcur == NULL) return 0; - *val = dev->clcur->list[dev->clcur->rdptr++]; + if (dev->clcur->rdptr < dev->clcur->wrptr) + *val = dev->clcur->list[dev->clcur->rdptr++]; + else + *val = 0; /* If we've reached the end, reset to the beginning and * (if repeating) run the repeat */ @@ -2139,6 +2162,7 @@ pgc_write(uint32_t addr, uint8_t val, void *priv) if (dev->mapram[addr] != val) { dev->mapram[addr] = val; + switch (addr) { case 0x300: /* input write pointer */ if (dev->waiting_input_fifo && @@ -2174,7 +2198,7 @@ pgc_write(uint32_t addr, uint8_t val, void *priv) dev->mapram[0x30d] = dev->mapram[0x30c]; break; - case 0x3ff: /* reboot the PGC */ + case 0x3ff: /* reboot the PGC */ pgc_wake(dev); break; } @@ -2226,9 +2250,8 @@ pgc_cga_text(pgc_t *dev, int w) ma += (dev->displine / pitch) * w; for (x = 0; x < w; x++) { - chr = addr[0]; - attr = addr[1]; - addr += 2; + chr = *addr++; + attr = *addr++; /* Cursor enabled? */ if (ma == ca && (dev->cgablink & 8) && @@ -2239,13 +2262,13 @@ pgc_cga_text(pgc_t *dev, int w) drawcursor = 0; if (dev->mapram[0x3d8] & 0x20) { - cols[1] = attr & 15; - cols[0] = (attr >> 4) & 7; + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; if ((dev->cgablink & 8) && (attr & 0x80) && !drawcursor) cols[1] = cols[0]; } else { - cols[1] = attr & 15; - cols[0] = attr >> 4; + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; } for (c = 0; c < cw; c++) { @@ -2272,8 +2295,8 @@ pgc_cga_gfx40(pgc_t *dev) uint8_t *addr; uint16_t dat; - cols[0] = dev->mapram[0x3d9] & 15; - col = (dev->mapram[0x3d9] & 16) ? 8 : 0; + cols[0] = (dev->mapram[0x3d9] & 15) + 16; + col = ((dev->mapram[0x3d9] & 16) ? 8 : 0) + 16; if (dev->mapram[0x3d8] & 4) { cols[1] = col | 3; @@ -2312,8 +2335,8 @@ pgc_cga_gfx80(pgc_t *dev) uint8_t *addr; uint16_t dat; - cols[0] = 0; - cols[1] = dev->mapram[0x3d9] & 15; + cols[0] = 16; + cols[1] = (dev->mapram[0x3d9] & 15) + 16; for (x = 0; x < 40; x++) { addr = &dev->cga_vram[(ma + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff]; @@ -2332,7 +2355,6 @@ void pgc_cga_poll(pgc_t *dev) { uint32_t cols[2]; - int c; if (! dev->linepos) { dev->vidtime += dev->dispofftime; @@ -2352,13 +2374,10 @@ pgc_cga_poll(pgc_t *dev) else pgc_cga_text(dev, 40); } else { - cols[0] = ((dev->mapram[0x03d8] & 0x12) == 0x12) ? 0 : (dev->mapram[0x03d9] & 15); + cols[0] = ((dev->mapram[0x03d8] & 0x12) == 0x12) ? 0 : ((dev->mapram[0x03d9] & 15) + 16); cga_hline(buffer, 0, dev->displine, PGC_CGA_WIDTH, cols[0]); } - for (c = 0; c < PGC_CGA_WIDTH; c++) - ((uint32_t *)buffer32->line[dev->displine])[c] = *((uint32_t *)&cgapal[buffer->line[dev->displine][c] & 0x0f]); - if (++dev->displine == PGC_CGA_HEIGHT) { dev->mapram[0x3da] |= 8; dev->cgadispon = 0; @@ -2383,7 +2402,7 @@ pgc_cga_poll(pgc_t *dev) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); frames++; /* We have a fixed 640x400 screen for CGA modes. */ @@ -2434,14 +2453,13 @@ pgc_poll(void *priv) * 224. */ y = dev->displine - 2 * dev->pan_y; for (x = 0; x < dev->screenw; x++) { - if (x + dev->pan_x < dev->maxw) { - buffer->line[dev->displine][x] = dev->palette[dev->vram[y * dev->maxw + x]]; - } else { - buffer->line[dev->displine][x] = dev->palette[0]; - } + if (x + dev->pan_x < dev->maxw) + ((uint32_t *)buffer32->line[dev->displine])[x] = dev->palette[dev->vram[y * dev->maxw + x]]; + else + ((uint32_t *)buffer32->line[dev->displine])[x] = dev->palette[0]; } } else { - cga_hline(buffer, 0, dev->displine, dev->screenw, dev->palette[0]); + cga_hline(buffer32, 0, dev->displine, dev->screenw, dev->palette[0]); } if (++dev->displine == dev->screenh) { @@ -2557,7 +2575,6 @@ pgc_init(pgc_t *dev, int maxw, int maxh, int visw, int vish, dev->pgc_wake_thread = thread_create_event(); dev->pgc_thread = thread_create(pgc_thread, dev); -pclog_repeat(0); timer_add(pgc_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); timer_add(wake_timer, &dev->wake_timer, &dev->wake_timer, (void *)dev); diff --git a/src/devices/video/vid_pgc.h b/src/devices/video/vid_pgc.h index e99a5ea..2b273ae 100644 --- a/src/devices/video/vid_pgc.h +++ b/src/devices/video/vid_pgc.h @@ -8,7 +8,7 @@ * * Definitions for the PGC driver. * - * Version: @(#)vid_pgc.h 1.0.2 2019/03/02 + * Version: @(#)vid_pgc.h 1.0.2 2019/03/03 * * Authors: Fred N. van Kempen, * John Elliott, @@ -101,6 +101,7 @@ typedef struct pgc { uint8_t color; uint8_t tjust_h; /* hor alignment 1=left 2=ctr 3=right*/ uint8_t tjust_v; /* vert alignment 1=bottom 2=ctr 3=top*/ + int32_t tsize; /* horizontal spacing */ int32_t x, y, z; /* drawing position */ @@ -126,8 +127,9 @@ typedef struct pgc { uint16_t ma, maback; int oddeven; - int dispontime, dispofftime; - int64_t vidtime; + int64_t dispontime, + dispofftime, + vidtime; int drawcursor; diff --git a/src/devices/video/vid_sigma.c b/src/devices/video/vid_sigma.c index 61d4656..33936db 100644 --- a/src/devices/video/vid_sigma.c +++ b/src/devices/video/vid_sigma.c @@ -41,13 +41,13 @@ * 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.2 2018/11/03 + * Version: @(#)vid_sigma.c 1.0.3 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, * John Elliott, * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018,2019 Fred N. van Kempen. * Copyright 2018 Miran Grca. * Copyright 2018 John Elliott. * @@ -165,6 +165,8 @@ typedef struct { + const char *name; + mem_map_t mapping, bios_ram; @@ -213,6 +215,8 @@ typedef struct { int64_t vidtime; uint8_t *vram; + uint8_t fontdat[256][8]; /* 8x8 font */ + uint8_t fontdat16[256][16]; /* 8x16 font */ uint8_t bram[2048]; uint8_t palette[16]; } sigma_t; @@ -485,16 +489,16 @@ sigma_text80(sigma_t *dev) if (drawcursor) { 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; + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(dev->fontdat16[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; + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(dev->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]; + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(dev->fontdat16[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]; + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(dev->fontdat[chr][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } ++ma; @@ -540,12 +544,12 @@ sigma_text40(sigma_t *dev) 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; + buffer->line[dev->displine][(x << 4) + 2*c + 9] = cols[(dev->fontdat16[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]; + buffer->line[dev->displine][(x << 4) + 2*c + 9] = cols[(dev->fontdat16[chr][dev->sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; } } ma++; @@ -836,11 +840,47 @@ sigma_poll(void *priv) } +static int +load_font(sigma_t *dev, const wchar_t *s) +{ + FILE *fp; + int c; + + fp = plat_fopen(rom_path(s), L"rb"); + if (fp == NULL) { + ERRLOG("%s: cannot load font '%ls'\n", dev->name, s); + return(0); + } + + /* The first 4K of the character ROM holds an 8x8 font. */ + for (c = 0; c < 256; c++) { + (void)fread(&dev->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(&dev->fontdat16[c][0], 1, 16, fp); + + (void)fclose(fp); + + return(1); +} + + static void * sigma_init(const device_t *info) { - sigma_t *dev = malloc(sizeof(sigma_t)); - memset(dev, 0, sizeof(sigma_t)); + sigma_t *dev; + + dev = (sigma_t *)mem_alloc(sizeof(sigma_t)); + memset(dev, 0x00, sizeof(sigma_t)); + dev->name = info->name; + + if (! load_font(dev, FONT_ROM_PATH)) { + free(dev); + return(NULL); + } dev->enable_nmi = device_get_config_int("enable_nmi"); @@ -855,8 +895,6 @@ sigma_init(const device_t *info) 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); diff --git a/src/devices/video/vid_svga_render.c b/src/devices/video/vid_svga_render.c index 656e695..010cd42 100644 --- a/src/devices/video/vid_svga_render.c +++ b/src/devices/video/vid_svga_render.c @@ -8,13 +8,13 @@ * * SVGA renderers. * - * Version: @(#)vid_svga_render.c 1.0.13 2018/10/22 + * Version: @(#)vid_svga_render.c 1.0.14 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -246,9 +246,9 @@ svga_render_text_80_ksc5601(svga_t *svga) if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { if ((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc]; + dat = fontdatk_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc]; else if (nextchr & 0x80) - dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc]; + dat = fontdatk[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc]; else dat = 0xff; } else { @@ -292,9 +292,9 @@ svga_render_text_80_ksc5601(svga_t *svga) } if ((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc + 16]; + dat = fontdatk_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc + 16]; else if (nextchr & 0x80) - dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16]; + dat = fontdatk[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16]; else dat = 0xff; diff --git a/src/devices/video/vid_wy700.c b/src/devices/video/vid_wy700.c index fff7d87..e806057 100644 --- a/src/devices/video/vid_wy700.c +++ b/src/devices/video/vid_wy700.c @@ -53,13 +53,13 @@ * What doesn't work, is untested or not well understood: * - Cursor detach (commands 4 and 5) * - * Version: @(#)vid_wy700.c 1.0.5 2018/09/22 + * Version: @(#)vid_wy700.c 1.0.6 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -93,13 +93,14 @@ #include "../../timer.h" #include "../../device.h" #include "../system/pit.h" +#include "../../plat.h" #include "video.h" #define WY700_XSIZE 1280 #define WY700_YSIZE 800 -#define BIOS_ROM_PATH L"video/wyse/wyse700/wy700.rom" +#define FONT_ROM_PATH L"video/wyse/wyse700/wy700.rom" /* The microcontroller sets up the real CRTC with one of five fixed mode @@ -186,11 +187,9 @@ static const uint8_t mode_40x24[] = { }; -/* Font ROM: Two fonts, each containing 256 characters, 16x16 pixels */ -extern uint8_t fontdatw[512][32]; - - typedef struct { + const char *name; + mem_map_t mapping; /* The microcontroller works by watching four ports: @@ -239,6 +238,9 @@ typedef struct { /* ... and MDA emulation. */ int mdacols[256][2][2]; + /* Font ROM: Two fonts, each containing 256 characters, 16x16 pixels */ + uint8_t fontdat[512][32]; + uint8_t *vram; } wy700_t; @@ -528,14 +530,13 @@ text_line(wy700_t *dev) int cw = (dev->wy700_mode == 0) ? 32 : 16; uint8_t chr, attr; uint8_t bitmap[2]; - uint8_t *fontbase = &fontdatw[0][0]; + uint8_t *fontbase = &dev->fontdat[0][0]; int blink, c; int drawcursor, cursorline; int mda = 0; uint16_t addr; uint8_t sc; - /* The fake CRTC character height register selects whether MDA or CGA * attributes are used */ if (dev->cga_crtc[9] == 0 || dev->cga_crtc[9] == 13) { @@ -854,6 +855,27 @@ wy700_poll(void *priv) } +static int +load_font(wy700_t *dev, const wchar_t *s) +{ + FILE *fp; + int c; + + fp = plat_fopen(rom_path(s), L"rb"); + if (fp == NULL) { + ERRLOG("%s: cannot load font '%ls'\n", dev->name, s); + return(0); + } + + for (c = 0; c < 512; c++) + (void)fread(&dev->fontdat[c][0], 1, 32, fp); + + (void)fclose(fp); + + return(1); +} + + static void * wy700_init(const device_t *info) { @@ -862,12 +884,16 @@ wy700_init(const device_t *info) dev = (wy700_t *)mem_alloc(sizeof(wy700_t)); memset(dev, 0x00, sizeof(wy700_t)); + dev->name = info->name; - /* 128k video RAM */ + if (! load_font(dev, FONT_ROM_PATH)) { + free(dev); + return(NULL); + } + + /* 128K video RAM */ dev->vram = (uint8_t *)mem_alloc(0x20000); - video_load_font(BIOS_ROM_PATH, 3); - timer_add(wy700_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in @@ -979,7 +1005,7 @@ wy700_close(void *priv) static int wy700_available(void) { - return rom_present(BIOS_ROM_PATH); + return rom_present(FONT_ROM_PATH); } diff --git a/src/devices/video/video.c b/src/devices/video/video.c index 0483645..02657ee 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.25 2019/03/02 + * Version: @(#)video.c 1.0.25 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -91,14 +91,15 @@ #ifdef ENABLE_VIDEO_LOG int video_do_log = ENABLE_VIDEO_LOG; #endif + +/* These will go away soon. */ +uint8_t fontdat[256][8]; /* IBM CGA font */ +uint8_t fontdatm[256][16]; /* IBM MDA font */ +dbcs_font_t *fontdatk = NULL, /* Korean KSC-5601 font */ + *fontdatk_user = NULL; /* Korean KSC-5601 font (user)*/ + bitmap_t *buffer = NULL, *buffer32 = NULL; -uint8_t fontdat[2048][8]; /* IBM CGA font */ -uint8_t fontdatm[2048][16]; /* IBM MDA font */ -uint8_t fontdatw[512][32]; /* Wyse700 font */ -uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ -dbcs_font_t *fontdatksc5601 = NULL, /* Korean KSC-5601 font */ - *fontdatksc5601_user = NULL; /* Korean KSC-5601 font (user)*/ uint32_t pal_lookup[256]; int xsize = 1, ysize = 1; @@ -884,14 +885,14 @@ video_type(void) void video_reset_font(void) { - if (fontdatksc5601 != NULL) { - free(fontdatksc5601); - fontdatksc5601 = NULL; + if (fontdatk != NULL) { + free(fontdatk); + fontdatk = NULL; } - if (fontdatksc5601_user != NULL) { - free(fontdatksc5601_user); - fontdatksc5601_user = NULL; + if (fontdatk_user != NULL) { + free(fontdatk_user); + fontdatk_user = NULL; } } @@ -901,11 +902,11 @@ void video_load_font(const wchar_t *s, int format) { FILE *fp; - int c, d; + int c; fp = plat_fopen(rom_path(s), L"rb"); if (fp == NULL) { - ERRLOG("VIDEO: cannot load font '%ls', fmt=%d\n", s, format); + ERRLOG("VIDEO: cannot load font '%ls', fmt=%i\n", s, format); return; } @@ -917,81 +918,15 @@ video_load_font(const wchar_t *s, int format) (void)fread(&fontdatm[c][8], 1, 8, fp); break; - case 1: /* PC200 */ - for (c = 0; c < 256; c++) - (void)fread(&fontdatm[c][0], 1, 8, fp); - for (c = 0; c < 256; c++) - (void)fread(&fontdatm[c][8], 1, 8, fp); - (void)fseek(fp, 4096, SEEK_SET); - for (c = 0; c < 256; c++) { - (void)fread(&fontdat[c][0], 1, 8, fp); - for (d = 0; d < 8; d++) - (void)fgetc(fp); - } - break; - - case 2: /* CGA, thin font */ - case 8: /* CGA, thick font */ - if (format == 8) { + case 1: /* CGA, thin font */ + case 2: /* CGA, thick font */ + if (format == 2) { /* Use the second ("thick") font in the ROM. */ (void)fseek(fp, 2048, SEEK_SET); } for (c = 0; c < 256; c++) (void)fread(&fontdat[c][0], 1, 8, fp); break; - - case 3: /* Wyse 700 */ - for (c = 0; c < 512; c++) - (void)fread(&fontdatw[c][0], 1, 32, fp); - break; - - case 4: /* MDSI Genius */ - for (c = 0; c < 256; c++) - (void)fread(&fontdat8x12[c][0], 1, 16, fp); - break; - - case 5: /* Toshiba 3100e */ - for (d = 0; d < 2048; d += 512) { /* Four languages... */ - for (c = d; c < d+256; c++) - (void)fread(&fontdatm[c][8], 1, 8, fp); - for (c = d+256; c < d+512; c++) - (void)fread(&fontdatm[c][8], 1, 8, fp); - for (c = d; c < d+256; c++) - (void)fread(&fontdatm[c][0], 1, 8, fp); - for (c = d+256; c < d+512; c++) - (void)fread(&fontdatm[c][0], 1, 8, fp); - (void)fseek(fp, 4096, SEEK_CUR); /* Skip blank section */ - for (c = d; c < d+256; c++) - (void)fread(&fontdat[c][0], 1, 8, fp); - for (c = d+256; c < d+512; c++) - (void)fread(&fontdat[c][0], 1, 8, fp); - } - break; - - case 6: /* Korean KSC-5601 */ - if (fontdatksc5601 == NULL) - fontdatksc5601 = (dbcs_font_t *)mem_alloc(16384 * sizeof(dbcs_font_t)); - - if (fontdatksc5601_user == NULL) - fontdatksc5601_user = (dbcs_font_t *)mem_alloc(192 * sizeof(dbcs_font_t)); - - for (c = 0; c < 16384; c++) { - for (d = 0; d < 32; d++) - 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; } DEBUG("VIDEO: font #%i loaded\n", format); diff --git a/src/devices/video/video.h b/src/devices/video/video.h index b069762..66b978b 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.26 2019/03/01 + * Version: @(#)video.h 1.0.27 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -113,16 +113,17 @@ typedef rgb_t PALETTE[256]; extern int changeframecount; +/* These will go away soon. */ +extern uint8_t fontdat[256][8]; +extern uint8_t fontdatm[256][16]; +extern dbcs_font_t *fontdatk, + *fontdatk_user; + extern bitmap_t *buffer, *buffer32; extern PALETTE cgapal, cgapal_mono[6]; extern uint32_t pal_lookup[256]; -extern uint8_t fontdat[2048][8]; -extern uint8_t fontdatm[2048][16]; -extern uint8_t fontdat8x12[256][16]; -extern dbcs_font_t *fontdatksc5601, - *fontdatksc5601_user; extern uint32_t *video_6to8, *video_15to32, *video_16to32; @@ -335,6 +336,10 @@ extern void video_wait_for_buffer(void); extern void cgapal_rebuild(void); +#ifdef VIDEO_SVGA_H +extern int ati28800k_load_font(svga_t *, const wchar_t *); +#endif + extern void video_log(int level, const char *fmt, ...); extern void video_init(void); extern void video_close(void); diff --git a/src/devices/video/video_dev.c b/src/devices/video/video_dev.c index 6b2f4df..897cb89 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.32 2019/03/02 + * Version: @(#)video_dev.c 1.0.32 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -68,9 +68,7 @@ static const struct { /* Standard video controllers. */ { "mda", &mda_device }, { "cga", &cga_device }, -#if defined(DEV_BRANCH) { "pgc", &pgc_device }, -#endif { "ega", &ega_device }, { "vga", &vga_device }, { "hercules", &hercules_device }, @@ -105,9 +103,7 @@ static const struct { { "hercules_plus", &herculesplus_device }, { "incolor", &incolor_device }, { "genius", &genius_device }, -#if defined(DEV_BRANCH) { "im1024", &im1024_device }, -#endif { "oti037c", &oti037c_device }, { "oti067", &oti067_device }, { "oti077", &oti077_device }, diff --git a/src/machines/m_amstrad.c b/src/machines/m_amstrad.c index f404adc..123feac 100644 --- a/src/machines/m_amstrad.c +++ b/src/machines/m_amstrad.c @@ -32,7 +32,7 @@ * BIOSES: I need to re-do the bios.txt format so we can load non-BIOS * ROM files for a given machine, such as font roms here.. * - * Version: @(#)m_amstrad.c 1.0.21 2019/02/16 + * Version: @(#)m_amstrad.c 1.0.22 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -88,6 +88,7 @@ #include "../devices/video/video.h" #include "../devices/video/vid_cga.h" #include "../devices/video/vid_ega.h" +#include "../plat.h" #include "machine.h" @@ -132,6 +133,7 @@ typedef struct { int firstline, lastline; uint8_t *vram; + uint8_t fontdat[256][8]; /* 1512/200 */ } amsvid_t; typedef struct { @@ -346,10 +348,10 @@ vid_poll_1512(void *priv) } if (drawcursor) { for (c = 0; c < 8; c++) - buffer->line[vid->displine][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer->line[vid->displine][(x << 3) + c + 8] = cols[(vid->fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) - buffer->line[vid->displine][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + buffer->line[vid->displine][(x << 3) + c + 8] = cols[(vid->fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; } vid->ma++; } @@ -371,11 +373,11 @@ vid_poll_1512(void *priv) if (drawcursor) { for (c = 0; c < 8; c++) buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = - buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(vid->fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = - buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(vid->fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; } } } else if (! (vid->cgamode & 16)) { @@ -533,14 +535,31 @@ vid_poll_1512(void *priv) static void -vid_init_1512(amstrad_t *ams) +vid_init_1512(amstrad_t *ams, const wchar_t *fn, int num) { amsvid_t *vid; + FILE *fp; + int c; /* Allocate a video controller block. */ vid = (amsvid_t *)mem_alloc(sizeof(amsvid_t)); memset(vid, 0x00, sizeof(amsvid_t)); + /* Load the PC1512 CGA Character Set ROM. */ + fp = plat_fopen(rom_path(fn), L"rb"); + if (fp != NULL) { + if (num == 8) { + /* Use the second ("thick") font in the ROM. */ + (void)fseek(fp, 2048, SEEK_SET); + } + for (c = 0; c < 256; c++) + (void)fread(&vid->fontdat[c][0], 1, 8, fp); + (void)fclose(fp); + } else { + ERRLOG("AMSTRAD: cannot load font '%ls'\n", fn); + return; + } + vid->vram = (uint8_t *)mem_alloc(0x10000); vid->cgacol = 7; vid->cgamode = 0x12; @@ -581,8 +600,7 @@ vid_speed_change_1512(void *priv) static const device_t vid_1512_device = { "Amstrad PC1512 (video)", - 0, - 0, + 0, 0, NULL, vid_close_1512, NULL, NULL, vid_speed_change_1512, @@ -752,8 +770,7 @@ vid_speed_changed_1640(void *priv) static const device_t vid_1640_device = { "Amstrad PC1640 (video)", - 0, - 0, + 0, 0, NULL, vid_close_1640, NULL, NULL, vid_speed_changed_1640, @@ -841,15 +858,40 @@ vid_in_200(uint16_t addr, void *priv) static void -vid_init_200(amstrad_t *ams) +vid_init_200(amstrad_t *ams, const wchar_t *fn) { amsvid_t *vid; cga_t *cga; + FILE *fp; + int c, d; /* Allocate a video controller block. */ vid = (amsvid_t *)mem_alloc(sizeof(amsvid_t)); memset(vid, 0x00, sizeof(amsvid_t)); + /* Load the PC200 CGA Character Set ROM. */ + fp = plat_fopen(rom_path(fn), L"rb"); + if (fp != NULL) { + for (c = 0; c < 256; c++) + (void)fread(&fontdatm[c][0], 1, 8, fp); + for (c = 0; c < 256; c++) + (void)fread(&fontdatm[c][8], 1, 8, fp); + + (void)fseek(fp, 4096, SEEK_SET); + + for (c = 0; c < 256; c++) { + (void)fread(&fontdat[c][0], 1, 8, fp); + + for (d = 0; d < 8; d++) + (void)fgetc(fp); + } + + (void)fclose(fp); + } else { + ERRLOG("AMSTRAD: cannot load font '%ls'\n", fn); + return; + } + cga = &vid->cga; cga->vram = (uint8_t *)mem_alloc(0x4000); cga_init(cga); @@ -891,8 +933,7 @@ vid_speed_changed_200(void *priv) static const device_t vid_200_device = { "Amstrad PC200 (video)", - 0, - 0, + 0, 0, NULL, vid_close_200, NULL, NULL, vid_speed_changed_200, @@ -1219,6 +1260,59 @@ amstrad_common_init(const machine_t *model, void *arg, int type) nmi_init(); + switch(ams->type) { + case 0: /* 1512 */ + device_add(&fdc_xt_device); + if (video_card == VID_INTERNAL) { + /* Initialize the internal CGA controller. */ + vid_init_1512(ams, roms->fontfn, roms->fontnum); + device_add_ex(&vid_1512_device, ams->vid); + } + break; + + case 1: /* 1640 */ + device_add(&fdc_xt_device); + if (video_card == VID_INTERNAL) { + /* Initialize the internal CGA/EGA controller. */ + vid_init_1640(ams, roms->vidfn, roms->vidsz); + device_add_ex(&vid_1640_device, ams->vid); + } + break; + + case 2: /* PC200 */ + device_add(&fdc_xt_device); + if (video_card == VID_INTERNAL) { + /* Initialize the internal CGA controller. */ + vid_init_200(ams, roms->fontfn); + device_add_ex(&vid_200_device, ams->vid); + } + break; + + case 3: /* PC2086 */ + device_add(&fdc_at_actlow_device); + if (video_card == VID_INTERNAL) { + device_add(¶dise_pvga1a_pc2086_device); + video_inform(VID_TYPE_SPEC, &pvga1a_timing); + } + break; + + case 4: /* PC3086 */ + device_add(&fdc_at_actlow_device); + if (video_card == VID_INTERNAL) { + device_add(¶dise_pvga1a_pc3086_device); + video_inform(VID_TYPE_SPEC, &pvga1a_timing); + } + break; + + case 5: /* MEGAPC */ + device_add(&fdc_at_actlow_device); + if (video_card == VID_INTERNAL) { + device_add(¶dise_wd90c11_megapc_device); + video_inform(VID_TYPE_SPEC, &wd90c11_timing); + } + break; + } + device_add(&amstrad_nvr_device); //FIXME: parallel_remove_amstrad(); @@ -1235,64 +1329,6 @@ amstrad_common_init(const machine_t *model, void *arg, int type) io_sethandler(0xdead, 1, ams_read, NULL, NULL, ams_write, NULL, NULL, ams); - switch(ams->type) { - case 0: - device_add(&fdc_xt_device); - if (video_card == VID_INTERNAL) { - /* Load the PC1512 CGA Character Set ROM. */ - video_load_font(roms->fontfn, roms->fontnum); - - /* Initialize the internal CGA controller. */ - vid_init_1512(ams); - device_add_ex(&vid_1512_device, ams->vid); - } - break; - - case 1: - device_add(&fdc_xt_device); - if (video_card == VID_INTERNAL) { - /* Load the BIOS for the internal CGA/EGA. */ - vid_init_1640(ams, roms->vidfn, roms->vidsz); - device_add_ex(&vid_1640_device, ams->vid); - } - break; - - case 2: - device_add(&fdc_xt_device); - if (video_card == VID_INTERNAL) { - /* Load the PC200 CGA Character Set ROM. */ - video_load_font(roms->fontfn, roms->fontnum); - - vid_init_200(ams); - device_add_ex(&vid_200_device, ams->vid); - } - break; - - case 3: - device_add(&fdc_at_actlow_device); - if (video_card == VID_INTERNAL) { - device_add(¶dise_pvga1a_pc2086_device); - video_inform(VID_TYPE_SPEC, &pvga1a_timing); - } - break; - - case 4: - device_add(&fdc_at_actlow_device); - if (video_card == VID_INTERNAL) { - device_add(¶dise_pvga1a_pc3086_device); - video_inform(VID_TYPE_SPEC, &pvga1a_timing); - } - break; - - case 5: - device_add(&fdc_at_actlow_device); - if (video_card == VID_INTERNAL) { - device_add(¶dise_wd90c11_megapc_device); - video_inform(VID_TYPE_SPEC, &wd90c11_timing); - } - break; - } - /* Initialize the (custom) keyboard/mouse interface. */ ams->wantirq = 0; io_sethandler(0x0060, 7, diff --git a/src/machines/m_at_t3100e_vid.c b/src/machines/m_at_t3100e_vid.c index 707a06e..301184e 100644 --- a/src/machines/m_at_t3100e_vid.c +++ b/src/machines/m_at_t3100e_vid.c @@ -22,13 +22,13 @@ * 61 50 52 0F 19 06 19 19 02 0D 0B 0C MONO * 2D 28 22 0A 67 00 64 67 02 03 06 07 640x400 * - * Version: @(#)m_at_t3100e_vid.c 1.0.6 2018/09/22 + * Version: @(#)m_at_t3100e_vid.c 1.0.7 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -59,15 +59,18 @@ #include "../cpu/cpu.h" #include "../io.h" #include "../mem.h" +#include "../rom.h" #include "../timer.h" #include "../device.h" #include "../devices/video/video.h" #include "../devices/video/vid_cga.h" +#include "../plat.h" #include "m_at_t3100e.h" -#define T3100E_XSIZE 640 -#define T3100E_YSIZE 400 +#define FONT_ROM_PATH L"machines/toshiba/t3100e/t3100e_font.bin" +#define T3100E_XSIZE 640 +#define T3100E_YSIZE 400 /* Mapping of attributes to colours */ @@ -108,6 +111,9 @@ typedef struct { uint8_t video_options; uint8_t *vram; + + uint8_t fontdat[2048][8]; + uint8_t fontdatm[2048][16]; } t3100e_t; @@ -363,11 +369,11 @@ text_row80(t3100e_t *dev) if (drawcursor) { for (c = 0; c < 8; c++) { - ((uint32_t *)buffer32->line[dev->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + ((uint32_t *)buffer32->line[dev->displine])[(x << 3) + c] = cols[(dev->fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); } } else { for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[dev->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + ((uint32_t *)buffer32->line[dev->displine])[(x << 3) + c] = cols[(dev->fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; } ++ma; } @@ -427,11 +433,11 @@ text_row40(t3100e_t *dev) if (drawcursor) { for (c = 0; c < 8; c++) { - ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2] = ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2] = ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2 + 1] = cols[(dev->fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); } } else { for (c = 0; c < 8; c++) { - ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2] = ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2+1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2] = ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2+1] = cols[(dev->fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; } } ++ma; @@ -640,6 +646,44 @@ t3100e_poll(void *priv) } +static int +load_font(t3100e_t *dev, const wchar_t *s) +{ + FILE *fp; + int c, d; + + fp = plat_fopen(rom_path(s), L"rb"); + if (fp == NULL) { + ERRLOG("T3100e: cannot load font '%ls'\n", s); + return(0); + } + + /* Fonts for 4 languages... */ + for (d = 0; d < 2048; d += 512) { + for (c = d; c < d+256; c++) + (void)fread(&dev->fontdatm[c][8], 1, 8, fp); + for (c = d+256; c < d+512; c++) + (void)fread(&dev->fontdatm[c][8], 1, 8, fp); + for (c = d; c < d+256; c++) + (void)fread(&dev->fontdatm[c][0], 1, 8, fp); + for (c = d+256; c < d+512; c++) + (void)fread(&dev->fontdatm[c][0], 1, 8, fp); + + /* Skip blank section. */ + (void)fseek(fp, 4096, SEEK_CUR); + + for (c = d; c < d+256; c++) + (void)fread(&dev->fontdat[c][0], 1, 8, fp); + for (c = d+256; c < d+512; c++) + (void)fread(&dev->fontdat[c][0], 1, 8, fp); + } + + (void)fclose(fp); + + return(1); +} + + static void * t3100e_init(const device_t *info) { @@ -648,6 +692,11 @@ t3100e_init(const device_t *info) dev = (t3100e_t *)mem_alloc(sizeof(t3100e_t)); memset(dev, 0x00, sizeof(t3100e_t)); + if (! load_font(dev, FONT_ROM_PATH)) { + free(dev); + return(NULL); + } + cga_init(&dev->cga); dev->internal = 1; diff --git a/src/machines/machine_table.c b/src/machines/machine_table.c index 2dd6c6b..46ef9d7 100644 --- a/src/machines/machine_table.c +++ b/src/machines/machine_table.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine_table.c 1.0.34 2019/02/16 + * Version: @(#)machine_table.c 1.0.35 2019/03/03 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -115,7 +115,7 @@ const machine_t machines[] = { { "[286 ISA] Hyundai Super-286TR", "hyundai_super286tr", L"hyundai/super286tr", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, m_at_scat_init, NULL, NULL }, { "[286 ISA] Samsung SPC-4200P", "samsung_spc4200p", L"samsung/spc4200p", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 128, m_at_scat_init, NULL, NULL }, { "[286 ISA] Samsung SPC-4216P", "samsung_spc4216p", L"samsung/spc4216p", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 128, m_at_scat_spc4216p_init, NULL, NULL }, - { "[286 ISA] Toshiba T3100e", "toshiba_t3100e", L"toshiba/t3100e", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 64, m_at_t3100e_init, NULL, NULL }, + { "[286 ISA] Toshiba T3100e", "toshiba_t3100e", L"toshiba/t3100e", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_HDC, 1024, 5120, 256, 64, m_at_t3100e_init, NULL, NULL }, { "[286 ISA] Trigem 286M", "tg286m", L"trigem/tg286m", 8, {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 128, m_at_tg286m_init, NULL, NULL }, { "[286 MCA] IBM PS/2 model 50", "ibm_ps2_m50", L"ibm/ps2_m50", -1, {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 1, 10, 1, 64, m_ps2_model_50_init, NULL, NULL },