Merge branch '86Box:master' into master

This commit is contained in:
bozoscum
2025-10-30 15:33:06 +08:00
committed by GitHub
5 changed files with 352 additions and 145 deletions

View File

@@ -33,6 +33,13 @@ typedef struct t1kvid_t {
uint8_t planar_ctrl;
uint8_t lp_strobe;
uint8_t baseline_hsyncpos;
uint8_t baseline_vsyncpos;
bool baseline_ready;
int hsync_offset;
int vsync_offset;
int vsync_offset_pending;
int linepos;
int displine;
int scanline;
@@ -51,6 +58,7 @@ typedef struct t1kvid_t {
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
pc_timer_t calib_timer;
int firstline;
int lastline;

View File

@@ -1105,6 +1105,9 @@ extern int machine_at_via809ds_init(const machine_t *);
/* SiS 5571 */
extern int machine_at_cb52xsi_init(const machine_t *);
#ifdef EMU_DEVICE_H
extern const device_t ms5146_device;
#endif
extern int machine_at_ms5146_init(const machine_t *);
#ifdef EMU_DEVICE_H
extern const device_t r534f_device;

View File

@@ -1825,17 +1825,72 @@ machine_at_cb52xsi_init(const machine_t *model)
return ret;
}
static const device_config_t ms5146_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "ms5146",
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = { { 0 } },
.bios = {
{
.name = "AMIBIOS 6 (071595) - Revision 1.1",
.internal_name = "ms5146",
.bios_type = BIOS_NORMAL,
.files_no = 1,
.local = 0,
.size = 131072,
.files = { "roms/machines/ms5146/A546MS11.ROM", "" }
},
{
.name = "Award Modular BIOS v4.51PG - Revision 2.1",
.internal_name = "ms5146_451pg",
.bios_type = BIOS_NORMAL,
.files_no = 1,
.local = 0,
.size = 131072,
.files = { "roms/machines/ms5146/W546MS21.BIN", "" }
},
{ .files_no = 0 }
}
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t ms5146_device = {
.name = "MSI MS-5146",
.internal_name = "ms5146_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = ms5146_config
};
int
machine_at_ms5146_init(const machine_t *model)
{
int ret;
int ret = 0;
const char *fn;
ret = bios_load_linear("roms/machines/ms5146/A546MS11.ROM",
0x000e0000, 131072, 0);
if (bios_only || !ret)
/* No ROMs available */
if (!device_available(model->device))
return ret;
device_context(model->device);
fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000e0000, 131072, 0);
device_context_restore();
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST);

View File

@@ -6851,7 +6851,7 @@ const machine_t machines[] = {
},
/* Has IBM PS/55 5551-Sxx, Txx stage 2 firmware. */
{
.name = "[MCA] IBM PS/55 model 5550-T",
.name = "[MCA] IBM PS/55 model 5550-S/T Stage II",
.internal_name = "ibmps55_m50t",
.type = MACHINE_TYPE_386DX,
.chipset = MACHINE_CHIPSET_PROPRIETARY,
@@ -6893,50 +6893,6 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* Has IBM PS/55 5551-V0x, V1x firmware. */
{
.name = "[MCA] IBM PS/55 model 5550-V",
.internal_name = "ibmps55_m50v",
.type = MACHINE_TYPE_386DX,
.chipset = MACHINE_CHIPSET_PROPRIETARY,
.init = machine_ps55_model_50v_init,
.p1_handler = machine_generic_p1_handler,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_386DX | CPU_PKG_486BL,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PS2_MCA,
.flags = MACHINE_VIDEO | MACHINE_KEYBOARD_JIS | MACHINE_APM,
.ram = {
.min = 4096,
.max = 16384,
.step = 4096
},
.nvrmask = 63,
.jumpered_ecp_dma = 0,
.default_jumpered_ecp_dma = -1,
.kbc_device = &kbc_at_device,
.kbc_params = KBC_VEN_IBM,
.kbc_p1 = 0x00000cf0,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.kbd_device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* 386DX/486 machines */
/* Winbond W83C42 - ASIC that clones AMI 'F'. */
@@ -7160,6 +7116,50 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* Has IBM PS/55 5551-V0x, V1x firmware. */
{
.name = "[MCA] IBM PS/55 model 5550-V0/V1",
.internal_name = "ibmps55_m50v",
.type = MACHINE_TYPE_386DX_486,
.chipset = MACHINE_CHIPSET_PROPRIETARY,
.init = machine_ps55_model_50v_init,
.p1_handler = machine_generic_p1_handler,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_386DX | CPU_PKG_486BL | CPU_PKG_SOCKET1,
.block = CPU_BLOCK_NONE,
.min_bus = 0,
.max_bus = 0,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PS2_MCA,
.flags = MACHINE_VIDEO | MACHINE_KEYBOARD_JIS | MACHINE_APM,
.ram = {
.min = 4096,
.max = 16384,
.step = 4096
},
.nvrmask = 63,
.jumpered_ecp_dma = 0,
.default_jumpered_ecp_dma = -1,
.kbc_device = &kbc_at_device,
.kbc_params = KBC_VEN_IBM,
.kbc_p1 = 0x00000cf0,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.kbd_device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* 486 machines - Socket 1 */
/* Has JetKey V5 KBC Firmware - we now have a photo of the board and its POST
@@ -15410,7 +15410,7 @@ const machine_t machines[] = {
PC87306 Super I/O chip, command 0xA1 returns '5'.
Command 0xA0 copyright string: (C)1994 AMI . */
{
.name = "[i430VX] Packard Bell Orlando/2D/2D/MMX (PB680/PB682/PB683/PB685)",
.name = "[i430VX] Packard Bell Orlando/2D/3D/MMX (PB680/PB682/PB683/PB685)",
.internal_name = "pb680",
.type = MACHINE_TYPE_SOCKET7,
.chipset = MACHINE_CHIPSET_INTEL_430VX,
@@ -16221,7 +16221,7 @@ const machine_t machines[] = {
.kbc_p1 = 0x00000cf0,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &ms5146_device,
.kbd_device = NULL,
.fdc_device = NULL,
.sio_device = NULL,

View File

@@ -16,6 +16,7 @@
* Copyright 2016-2019 Miran Grca.
* Copyright 2025 starfrost
*/
#include <stdbool.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -162,6 +163,48 @@ vid_update_latch(t1kvid_t *vid)
vid->crtc[0x11] = lp_latch & 0xff;
}
static void
baseline_calib_start(t1kvid_t *vid)
{
vid->baseline_ready = false;
vid->hsync_offset = 0;
vid->vsync_offset = 0;
timer_on_auto(&vid->calib_timer, 100000.0);
}
static void
baseline_calib_finish(void *priv)
{
tandy_t *dev = (tandy_t *) priv;
t1kvid_t *vid = dev->vid;
vid->baseline_hsyncpos = vid->crtc[2];
vid->baseline_vsyncpos = vid->crtc[7];
vid->baseline_ready = true;
}
static void
vid_update_display_offset(t1kvid_t *vid, uint8_t reg)
{
int hsync_scale = (vid->mode & 1) ? 8 : 16;
int vsync_scale = vid->crtc[9] + 1;
if (!vid->baseline_ready) {
vid->hsync_offset = 0;
vid->vsync_offset = 0;
return;
} else {
switch (reg) {
case 2:
vid->hsync_offset = ((int)vid->baseline_hsyncpos - (int)vid->crtc[2]) * hsync_scale;
break;
case 7:
vid->vsync_offset_pending = ((int)vid->baseline_vsyncpos - (int)vid->crtc[7]) * vsync_scale;
break;
}
}
}
void
tandy_vid_out(uint16_t addr, uint8_t val, void *priv)
{
@@ -188,12 +231,16 @@ tandy_vid_out(uint16_t addr, uint8_t val, void *priv)
vid->fullchange = changeframecount;
recalc_timings(dev);
}
if (vid->crtcreg == 0x02 || vid->crtcreg == 0x07)
vid_update_display_offset(vid, vid->crtcreg);
}
break;
case 0x03d8:
old = vid->mode;
vid->mode = val;
if (old != val)
baseline_calib_start(vid);
if ((old ^ val) & 0x01)
recalc_timings(dev);
if (!dev->is_sl2)
@@ -337,7 +384,7 @@ vid_read(uint32_t addr, void *priv)
}
static void
vid_render(tandy_t *dev, int line)
vid_render(tandy_t *dev, int line, int hos_offs)
{
t1kvid_t *vid = dev->vid;
uint16_t cursoraddr = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff;
@@ -349,53 +396,91 @@ vid_render(tandy_t *dev, int line)
uint16_t dat;
int col;
int cols[4];
uint32_t border_val;
int out_x;
int c_start;
cols[0] = (vid->array[2] & 0xf) + 16;
for (c = 0; c < 8; c++) {
if (vid->array[3] & 4) {
buffer32->line[line][c] = cols[0];
if (vid->mode & 1)
buffer32->line[line][c + (vid->crtc[1] << 3) + 8] = cols[0];
else
buffer32->line[line][c + (vid->crtc[1] << 4) + 8] = cols[0];
} else if ((vid->mode & 0x12) == 0x12) {
buffer32->line[line][c] = 0;
if (vid->mode & 1)
buffer32->line[line][c + (vid->crtc[1] << 3) + 8] = 0;
else
buffer32->line[line][c + (vid->crtc[1] << 4) + 8] = 0;
if (line < 0) {
if (dev->is_sl2 && (vid->array[5] & 1)) {
vid->memaddr += vid->crtc[1] * 2;
} else {
buffer32->line[line][c] = buffer32->line[(line) + 1][c] = (vid->col & 15) + 16;
if (vid->mode & 1)
buffer32->line[line][c + (vid->crtc[1] << 3) + 8] = (vid->col & 15) + 16;
else
buffer32->line[line][c + (vid->crtc[1] << 4) + 8] = (vid->col & 15) + 16;
vid->memaddr += vid->crtc[1];
}
return;
}
if (vid->array[3] & 4) {
border_val = cols[0];
} else if ((vid->mode & 0x12) == 0x12) {
border_val = 0;
} else {
border_val = (vid->col & 15) + 16;
}
if (vid->array[3] & 4) {
for (c = 0; c < hos_offs; c++) {
buffer32->line[line][c] = border_val;
}
} else if ((vid->mode & 0x12) == 0x12) {
for (c = 0; c < hos_offs; c++) {
buffer32->line[line][c] = border_val;
}
} else {
for (c = 0; c < hos_offs; c++) {
buffer32->line[line][c] = buffer32->line[(line) + 1][c] = border_val;
}
}
if (vid->mode & 1) {
out_x = (vid->crtc[1] << 3) + hos_offs;
} else {
out_x = (vid->crtc[1] << 4) + hos_offs;
}
c_start = out_x < 0 ? -out_x : 0;
for (c = c_start; c < 8 - vid->hsync_offset; c++) {
buffer32->line[line][out_x + c] = border_val;
}
if (dev->is_sl2 && (vid->array[5] & 1)) { /*640x200x16*/
for (x = 0; x < vid->crtc[1] * 2; x++) {
dat = (vid->vram[(vid->memaddr << 1) & 0xffff] << 8) | vid->vram[((vid->memaddr << 1) + 1) & 0xffff];
vid->memaddr++;
buffer32->line[line][(x << 2) + 8] = vid->array[((dat >> 12) & 0xf) + 16] + 16;
buffer32->line[line][(x << 2) + 9] = vid->array[((dat >> 8) & 0xf) + 16] + 16;
buffer32->line[line][(x << 2) + 10] = vid->array[((dat >> 4) & 0xf) + 16] + 16;
buffer32->line[line][(x << 2) + 11] = vid->array[(dat & 0xf) + 16] + 16;
out_x = (x << 2) + hos_offs;
if (out_x >= 0) {
buffer32->line[line][out_x] = vid->array[((dat >> 12) & 0xf) + 16] + 16;
buffer32->line[line][out_x + 1] = vid->array[((dat >> 8) & 0xf) + 16] + 16;
buffer32->line[line][out_x + 2] = vid->array[((dat >> 4) & 0xf) + 16] + 16;
buffer32->line[line][out_x + 3] = vid->array[(dat & 0xf) + 16] + 16;
} else if (out_x > -4) {
for (c = -out_x; c < 4; c++) {
buffer32->line[line][out_x + c] =
vid->array[((dat >> (12 - c * 4)) & 0xf) + 16] + 16;
}
}
}
} else if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/
for (x = 0; x < vid->crtc[1]; x++) {
dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000)] << 8) |
vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000) + 1];
vid->memaddr++;
buffer32->line[line][(x << 3) + 8] = buffer32->line[line][(x << 3) + 9] =
vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][(x << 3) + 10] = buffer32->line[line][(x << 3) + 11] =
vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][(x << 3) + 12] = buffer32->line[line][(x << 3) + 13] =
vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][(x << 3) + 14] = buffer32->line[line][(x << 3) + 15] =
vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16;
out_x = (x << 3) + hos_offs;
if (out_x >= 0) {
buffer32->line[line][out_x] = buffer32->line[line][out_x + 1] =
vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][out_x + 2] = buffer32->line[line][out_x + 3] =
vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][out_x + 4] = buffer32->line[line][out_x + 5] =
vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][out_x + 6] = buffer32->line[line][out_x + 7] =
vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16;
} else if (out_x > -8) {
for (c = -out_x; c < 8; c++) {
buffer32->line[line][out_x + c] =
vid->array[((dat >> 12 - (c >> 1) * 4) & vid->array[1] & 0x0f) + 16] + 16;
}
}
}
} else if (vid->array[3] & 0x10) { /*160x200x16*/
for (x = 0; x < vid->crtc[1]; x++) {
@@ -406,30 +491,43 @@ vid_render(tandy_t *dev, int line)
dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000)] << 8) |
vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000) + 1];
vid->memaddr++;
buffer32->line[line][(x << 4) + 8] = buffer32->line[line][(x << 4) + 9] =
buffer32->line[line][(x << 4) + 10] = buffer32->line[line][(x << 4) + 11] =
vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][(x << 4) + 12] = buffer32->line[line][(x << 4) + 13] =
buffer32->line[line][(x << 4) + 14] = buffer32->line[line][(x << 4) + 15] =
vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][(x << 4) + 16] = buffer32->line[line][(x << 4) + 17] =
buffer32->line[line][(x << 4) + 18] = buffer32->line[line][(x << 4) + 19] =
vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][(x << 4) + 20] = buffer32->line[line][(x << 4) + 21] =
buffer32->line[line][(x << 4) + 22] = buffer32->line[line][(x << 4) + 23] =
vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16;
out_x = (x << 4) + hos_offs;
if (out_x >= 0) {
buffer32->line[line][out_x] = buffer32->line[line][out_x + 1] =
buffer32->line[line][out_x + 2] = buffer32->line[line][out_x + 3] =
vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][out_x + 4] = buffer32->line[line][out_x + 5] =
buffer32->line[line][out_x + 6] = buffer32->line[line][out_x + 7] =
vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][out_x + 8] = buffer32->line[line][out_x + 9] =
buffer32->line[line][out_x + 10] = buffer32->line[line][out_x + 11] =
vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[line][out_x + 12] = buffer32->line[line][out_x + 13] =
buffer32->line[line][out_x + 14] = buffer32->line[line][out_x + 15] =
vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16;
} else if (out_x > -16) {
for (c = -out_x; c < 16; c++) {
buffer32->line[line][out_x + c] =
vid->array[((dat >> 12 - (c >> 2) * 4) & vid->array[1] & 0x0f) + 16] + 16;
}
}
}
} else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/
for (x = 0; x < vid->crtc[1]; x++) {
dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000)] << 8) |
vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 3) * 0x2000) + 1];
vid->memaddr++;
for (c = 0; c < 8; c++) {
chr = (dat >> 6) & 2;
chr |= ((dat >> 15) & 1);
buffer32->line[line][(x << 3) + 8 + c] =
vid->array[(chr & vid->array[1]) + 16] + 16;
dat <<= 1;
out_x = (x << 3) + hos_offs;
if (out_x > -8) {
c_start = out_x < 0 ? -out_x : 0;
dat <<= c_start;
for (c = c_start; c < 8; c++) {
chr = (dat >> 6) & 2;
chr |= ((dat >> 15) & 1);
buffer32->line[line][out_x + c] =
vid->array[(chr & vid->array[1]) + 16] + 16;
dat <<= 1;
}
}
}
} else if (vid->mode & 1) {
@@ -446,17 +544,22 @@ vid_render(tandy_t *dev, int line)
cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16;
cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16;
}
if (vid->scanline & 8) for (c = 0; c < 8; c++)
buffer32->line[line][(x << 3) + c + 8] =
((chr >= 0xb3) && (chr <= 0xdf)) ? cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0] : cols[0];
else for (c = 0; c < 8; c++) {
if (vid->scanline == 8)
buffer32->line[line][(x << 3) + c + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0];
else
buffer32->line[line][(x << 3) + c + 8] = cols[(fontdat[chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
out_x = (x << 3) + hos_offs;
if (out_x > -8) {
c_start = out_x < 0 ? -out_x : 0;
if (vid->scanline & 8) for (c = c_start; c < 8; c++) {
buffer32->line[line][out_x + c] =
((chr >= 0xb3) && (chr <= 0xdf)) ? cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0] : cols[0];
} else for (c = c_start; c < 8; c++) {
if (vid->scanline == 8)
buffer32->line[line][out_x + c] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0];
else
buffer32->line[line][out_x + c] = cols[(fontdat[chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
if (drawcursor) for (c = c_start; c < 8; c++) {
buffer32->line[line][out_x + c] ^= 15;
}
}
if (drawcursor) for (c = 0; c < 8; c++)
buffer32->line[line][(x << 3) + c + 8] ^= 15;
vid->memaddr++;
}
} else if (!(vid->mode & 2)) {
@@ -474,22 +577,31 @@ vid_render(tandy_t *dev, int line)
cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16;
}
vid->memaddr++;
if (vid->scanline & 8) for (c = 0; c < 8; c++)
buffer32->line[line][(x << 4) + (c << 1) + 8] =
buffer32->line[line][(x << 4) + (c << 1) + 1 + 8] =
((chr >= 0xb3) && (chr <= 0xdf)) ? cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0] : cols[0];
else for (c = 0; c < 8; c++) {
if (vid->scanline == 8)
buffer32->line[line][(x << 4) + (c << 1) + 8] =
buffer32->line[line][(x << 4) + (c << 1) + 1 + 8] =
cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0];
else
buffer32->line[line][(x << 4) + (c << 1) + 8] =
buffer32->line[line][(x << 4) + (c << 1) + 1 + 8] =
cols[(fontdat[chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
out_x = (x << 4) + hos_offs;
if (out_x > -16) {
c_start = out_x < 0 ? -out_x >> 1 : 0;
if (vid->scanline & 8) for (c = c_start; c < 8; c++) {
buffer32->line[line][out_x + (c << 1)] =
buffer32->line[line][out_x + 1 + (c << 1)] =
((chr >= 0xb3) && (chr <= 0xdf)) ? cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0] : cols[0];
} else for (c = c_start; c < 8; c++) {
if (vid->scanline == 8) {
buffer32->line[line][out_x + (c << 1)] =
buffer32->line[line][out_x + 1 + (c << 1)] =
cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0];
} else {
buffer32->line[line][out_x + (c << 1)] =
buffer32->line[line][out_x + 1 + (c << 1)] =
cols[(fontdat[chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
if (drawcursor) {
c_start = out_x < 0 ? -out_x : 0;
for (c = c_start; c < 16; c++) {
buffer32->line[line][out_x + c] ^= 15;
}
}
}
if (drawcursor) for (c = 0; c < 16; c++)
buffer32->line[line][(x << 4) + c + 8] ^= 15;
}
} else if (!(vid->mode & 16)) {
cols[0] = (vid->col & 15);
@@ -515,10 +627,15 @@ vid_render(tandy_t *dev, int line)
dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000)] << 8) |
vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000) + 1];
vid->memaddr++;
for (c = 0; c < 8; c++) {
buffer32->line[line][(x << 4) + (c << 1) + 8] =
buffer32->line[line][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
out_x = (x << 4) + hos_offs;
if (out_x > -16) {
c_start = out_x < 0 ? -out_x >> 1 : 0;
dat <<= (c_start > 0 ? c_start << 1 : 0);
for (c = c_start; c < 8; c++) {
buffer32->line[line][out_x + (c << 1)] =
buffer32->line[line][out_x + 1 + (c << 1)] = cols[dat >> 14];
dat <<= 2;
}
}
}
} else {
@@ -528,9 +645,14 @@ vid_render(tandy_t *dev, int line)
dat = (vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000)] << 8) |
vid->vram[((vid->memaddr << 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000) + 1];
vid->memaddr++;
for (c = 0; c < 16; c++) {
buffer32->line[line][(x << 4) + c + 8] = buffer32->line[(line) + 1][(x << 4) + c + 8] = cols[dat >> 15];
dat <<= 1;
out_x = (x << 4) + hos_offs;
if (out_x > -16) {
c_start = out_x < 0 ? -out_x : 0;
dat <<= (c_start > 0 ? c_start : 0);
for (c = c_start; c < 16; c++) {
buffer32->line[line][out_x + c] = buffer32->line[(line) + 1][out_x + c] = cols[dat >> 15];
dat <<= 1;
}
}
}
}
@@ -541,6 +663,9 @@ vid_render_blank(tandy_t *dev, int line)
{
t1kvid_t *vid = dev->vid;
if (line < 0)
return;
if (vid->array[3] & 4) {
if (vid->mode & 1)
hline(buffer32, 0, line, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16);
@@ -562,6 +687,9 @@ vid_render_process(tandy_t *dev, int line)
t1kvid_t *vid = dev->vid;
int x;
if (line < 0)
return;
if (vid->mode & 1)
x = (vid->crtc[1] << 3) + 16;
else
@@ -584,6 +712,9 @@ vid_poll(void *priv)
int oldvc;
int scanline_old;
int old_ma;
int hos_offs = 8 + vid->hsync_offset;
int displine_offs = vid->displine + vid->vsync_offset;
int displine_offs_double = (vid->displine << 1) + (vid->vsync_offset << 1);
if (!vid->linepos) {
timer_advance_u64(&vid->timer, vid->dispofftime);
@@ -600,39 +731,39 @@ vid_poll(void *priv)
vid->lastline = vid->displine;
switch (vid->double_type) {
default:
vid_render(dev, vid->displine << 1);
vid_render_blank(dev, (vid->displine << 1) + 1);
vid_render(dev, displine_offs_double, hos_offs);
vid_render_blank(dev, displine_offs_double + 1);
break;
case DOUBLE_NONE:
vid_render(dev, vid->displine);
vid_render(dev, displine_offs, hos_offs);
break;
case DOUBLE_SIMPLE:
old_ma = vid->memaddr;
vid_render(dev, vid->displine << 1);
vid_render(dev, displine_offs_double, hos_offs);
vid->memaddr = old_ma;
vid_render(dev, (vid->displine << 1) + 1);
vid_render(dev, displine_offs_double + 1, hos_offs);
break;
}
} else switch (vid->double_type) {
default:
vid_render_blank(dev, vid->displine << 1);
vid_render_blank(dev, displine_offs_double);
break;
case DOUBLE_NONE:
vid_render_blank(dev, vid->displine);
vid_render_blank(dev, displine_offs);
break;
case DOUBLE_SIMPLE:
vid_render_blank(dev, vid->displine << 1);
vid_render_blank(dev, (vid->displine << 1) + 1);
vid_render_blank(dev, displine_offs_double);
vid_render_blank(dev, displine_offs_double + 1);
break;
}
switch (vid->double_type) {
default:
vid_render_process(dev, vid->displine << 1);
vid_render_process(dev, (vid->displine << 1) + 1);
vid_render_process(dev, displine_offs_double);
vid_render_process(dev, displine_offs_double + 1);
break;
case DOUBLE_NONE:
vid_render_process(dev, vid->displine);
vid_render_process(dev, displine_offs);
break;
}
@@ -696,6 +827,7 @@ vid_poll(void *priv)
vid->cursoron = vid->blink & 16;
}
if (vid->vc == vid->crtc[7]) {
vid->vsync_offset = vid->vsync_offset_pending;
vid->dispon = 0;
vid->displine = 0;
vid->vsynctime = 16;
@@ -784,6 +916,8 @@ tandy_vid_close(void *priv)
{
tandy_t *dev = (tandy_t *) priv;
timer_on_auto(&dev->vid->calib_timer, 0.0);
free(dev->vid);
dev->vid = NULL;
}
@@ -795,6 +929,12 @@ tandy_vid_init(tandy_t *dev)
t1kvid_t *vid;
vid = calloc(1, sizeof(t1kvid_t));
vid->baseline_hsyncpos = 0;
vid->baseline_vsyncpos = 0;
vid->baseline_ready = false;
vid->hsync_offset = 0;
vid->vsync_offset = 0;
vid->vsync_offset_pending = 0;
vid->memctrl = -1;
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram);
@@ -814,6 +954,7 @@ tandy_vid_init(tandy_t *dev)
vid->b8000_mask = 0x3fff;
timer_add(&vid->timer, vid_poll, dev, 1);
timer_add(&vid->calib_timer, baseline_calib_finish, dev, 0);
mem_mapping_add(&vid->mapping, 0xb8000, 0x08000,
vid_read, NULL, NULL, vid_write, NULL, NULL, NULL, 0, dev);
io_sethandler(0x03d0, 16,