Merge branch 'master' into vmm

This commit is contained in:
Alexander Babikov
2025-06-22 03:16:00 +05:00
111 changed files with 6959 additions and 5408 deletions

View File

@@ -57,6 +57,7 @@ add_library(dev OBJECT
smbus_ali7101.c
smbus_piix4.c
smbus_sis5595.c
tulip_jumper.c
unittester.c
)

View File

@@ -212,7 +212,7 @@ isarom_init(const device_t *info)
static const device_config_t isarom_config[] = {
{
.name = "bios_fn",
.description = "BIOS File",
.description = "BIOS file",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -234,7 +234,7 @@ static const device_config_t isarom_config[] = {
},
{
.name = "bios_size",
.description = "BIOS Size:",
.description = "BIOS size",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -260,7 +260,7 @@ static const device_config_t isarom_config[] = {
static const device_config_t isarom_dual_config[] = {
{
.name = "bios_fn",
.description = "BIOS File (ROM #1)",
.description = "BIOS file (ROM #1)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -271,7 +271,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_addr",
.description = "BIOS Address (ROM #1)",
.description = "BIOS address (ROM #1)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -282,7 +282,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_size",
.description = "BIOS Size (ROM #1):",
.description = "BIOS size (ROM #1)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -304,7 +304,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_fn2",
.description = "BIOS File (ROM #2)",
.description = "BIOS file (ROM #2)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -315,7 +315,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_addr2",
.description = "BIOS Address (ROM #2)",
.description = "BIOS address (ROM #2)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -326,7 +326,7 @@ static const device_config_t isarom_dual_config[] = {
},
{
.name = "bios_size2",
.description = "BIOS Size (ROM #2):",
.description = "BIOS size (ROM #2)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -352,7 +352,7 @@ static const device_config_t isarom_dual_config[] = {
static const device_config_t isarom_quad_config[] = {
{
.name = "bios_fn",
.description = "BIOS File (ROM #1)",
.description = "BIOS file (ROM #1)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -363,7 +363,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_addr",
.description = "BIOS Address (ROM #1)",
.description = "BIOS address (ROM #1)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -374,7 +374,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_size",
.description = "BIOS Size (ROM #1):",
.description = "BIOS size (ROM #1)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -396,7 +396,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_fn2",
.description = "BIOS File (ROM #2)",
.description = "BIOS file (ROM #2)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -407,7 +407,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_addr2",
.description = "BIOS Address (ROM #2)",
.description = "BIOS address (ROM #2)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -418,7 +418,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_size2",
.description = "BIOS Size (ROM #2):",
.description = "BIOS size (ROM #2)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -440,7 +440,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_fn3",
.description = "BIOS File (ROM #3)",
.description = "BIOS file (ROM #3)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -451,7 +451,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_addr3",
.description = "BIOS Address (ROM #3)",
.description = "BIOS address (ROM #3)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -462,7 +462,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_size3",
.description = "BIOS Size (ROM #3):",
.description = "BIOS size (ROM #3)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,
@@ -484,7 +484,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_fn4",
.description = "BIOS File (ROM #4)",
.description = "BIOS file (ROM #4)",
.type = CONFIG_FNAME,
.default_string = NULL,
.default_int = 0,
@@ -495,7 +495,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_addr4",
.description = "BIOS Address (ROM #4)",
.description = "BIOS address (ROM #4)",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 0x00000,
@@ -506,7 +506,7 @@ static const device_config_t isarom_quad_config[] = {
},
{
.name = "bios_size4",
.description = "BIOS Size (ROM #4):",
.description = "BIOS size (ROM #4)",
.type = CONFIG_INT,
.default_string = NULL,
.default_int = 8192,

File diff suppressed because it is too large Load Diff

View File

@@ -109,7 +109,7 @@ static const device_config_t keycard_config[] = {
};
const device_t novell_keycard_device = {
.name = "Novell Netware 2.x Key Card",
.name = "Novell NetWare 2.x Key Card",
.internal_name = "mssystems",
.flags = DEVICE_ISA,
.local = 0,

103
src/device/tulip_jumper.c Normal file
View File

@@ -0,0 +1,103 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the Tulip Jumper Readout.
*
* Bits 7-5 = board number, 0-5 valid, 6, 7 invalid.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2025 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/sound.h>
#include <86box/chipset.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
typedef struct tulip_jumper_t {
uint8_t jumper;
} tulip_jumper_t;
#ifdef ENABLE_TULIP_JUMPER_LOG
int tulip_jumper_do_log = ENABLE_TULIP_JUMPER_LOG;
static void
tulip_jumper_log(const char *fmt, ...)
{
va_list ap;
if (tulip_jumper_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define tulip_jumper_log(fmt, ...)
#endif
static uint8_t
tulip_jumper_read(uint16_t addr, void *priv)
{
const tulip_jumper_t *dev = (tulip_jumper_t *) priv;
uint8_t ret = 0xff;
tulip_jumper_log("Tulip Jumper: Read %02x\n", dev->jumper);
ret = dev->jumper;
return ret;
}
static void
tulip_jumper_close(void *priv)
{
tulip_jumper_t *dev = (tulip_jumper_t *) priv;
free(dev);
}
static void *
tulip_jumper_init(const device_t *info)
{
tulip_jumper_t *dev = (tulip_jumper_t *) calloc(1, sizeof(tulip_jumper_t));
/* Return board number 05. */
dev->jumper = 0xbf;
io_sethandler(0x0d80, 0x0001, tulip_jumper_read, NULL, NULL, NULL, NULL, NULL, dev);
return dev;
}
const device_t tulip_jumper_device = {
.name = "Tulip Jumper Readout",
.internal_name = "tulip_jumper",
.flags = 0,
.local = 0,
.init = tulip_jumper_init,
.close = tulip_jumper_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -187,10 +187,18 @@ fdc_ctrl_reset(void *priv)
fdc->stat = 0x80;
fdc->pnum = fdc->ptot = 0;
fdc->st0 = 0;
fdc->lock = 0;
fdc->head = 0;
fdc->step = 0;
fdc->power_down = 0;
if (!fdc->lock) {
fdc->fifo = 0;
fdc->tfifo = 1;
fifo_reset(fdc->fifo_p);
fifo_set_len(fdc->fifo_p, fdc->tfifo + 1);
fifo_set_trigger_len(fdc->fifo_p, fdc->tfifo + 1);
}
}
sector_id_t
@@ -2374,6 +2382,8 @@ fdc_reset(void *priv)
fdc->swwp = 0;
fdc->disable_write = 0;
fdc->lock = 0;
fdc_ctrl_reset(fdc);
if (!(fdc->flags & FDC_FLAG_AT))

View File

@@ -183,7 +183,7 @@ static const device_config_t monster_fdc_config[] = {
#if 0
{
.name = "bios_size",
.description = "BIOS Size:",
.description = "BIOS size",
.type = CONFIG_HEX20,
.default_string = NULL,
.default_int = 32,

View File

@@ -201,6 +201,8 @@ extern const device_t vlsi_scamp_device;
extern const device_t wd76c10_device;
/* Miscellaneous Hardware */
extern const device_t tulip_jumper_device;
extern const device_t dell_jumper_device;
extern const device_t nec_mate_unk_device;

View File

@@ -0,0 +1,72 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Header files for the PCjr keyboard and video subsystems.
*
*
*
* Authors: Connor Hyde, <mario64crashed@gmail.com>
*
* Copyright 2025 starfrost
*/
#pragma once
#define PCJR_RGB 0
#define PCJR_COMPOSITE 1
typedef struct pcjr_s
{
/* Video Controller stuff. */
mem_mapping_t mapping;
uint8_t crtc[32];
int crtcreg;
int array_index;
uint8_t array[32];
int array_ff;
int memctrl;
uint8_t status;
int addr_mode;
uint8_t *vram;
uint8_t *b8000;
int linepos;
int displine;
int scanline;
int vc;
int dispon;
int cursorvisible; // Is the cursor visible on the current scanline?
int cursoron;
int blink;
int vsynctime;
int fullchange;
int vadj;
uint16_t memaddr;
uint16_t memaddr_backup;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int composite;
int apply_hd;
/* Keyboard Controller stuff. */
int latched;
int data;
int serial_data[44];
int serial_pos;
uint8_t pa;
uint8_t pb;
pc_timer_t send_delay_timer;
} pcjr_t;
void pcjr_recalc_timings(pcjr_t *pcjr);
// Note: This is a temporary solution until the pcjr video is made its own gfx card
void pcjr_vid_init(pcjr_t *pcjr);

View File

@@ -0,0 +1,95 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Header files for the Tandy keyboard and video subsystems.
*
*
*
* Authors: Connor Hyde, <mario64crashed@gmail.com>
*
* Copyright 2025 starfrost
*/
typedef struct t1kvid_t {
mem_mapping_t mapping;
mem_mapping_t vram_mapping;
uint8_t crtc[32];
int crtcreg;
int array_index;
uint8_t array[256];
int memctrl;
uint8_t mode;
uint8_t col;
uint8_t status;
uint8_t *vram;
uint8_t *b8000;
uint32_t b8000_mask;
uint32_t b8000_limit;
uint8_t planar_ctrl;
uint8_t lp_strobe;
int linepos;
int displine;
int scanline;
int vc;
int dispon;
int cursorvisible;
int cursoron;
int blink;
int fullchange;
int vsynctime;
int vadj;
uint16_t memaddr;
uint16_t memaddr_backup;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int composite;
} t1kvid_t;
typedef struct t1keep_t {
char *path;
int state;
int count;
int addr;
int clk;
uint16_t data;
uint16_t store[64];
} t1keep_t;
typedef struct tandy_t {
mem_mapping_t ram_mapping;
mem_mapping_t rom_mapping; /* SL2 */
uint8_t *rom; /* SL2 */
uint8_t ram_bank;
uint8_t rom_bank; /* SL2 */
int rom_offset; /* SL2 */
uint32_t base;
uint32_t mask;
int is_hx;
int is_sl2;
t1kvid_t *vid;
} tandy_t;
void tandy_vid_init(tandy_t* dev);
uint8_t tandy_vid_in(uint16_t addr, void* priv);
void tandy_vid_out(uint16_t addr, uint8_t val, void *priv);
void tandy_vid_close(void* priv);
void tandy_recalc_address_sl(tandy_t* dev); //this function is needed by both m_ and vid_tandy.c

View File

@@ -473,7 +473,9 @@ extern int machine_at_spc4216p_init(const machine_t *);
extern int machine_at_spc4620p_init(const machine_t *);
extern int machine_at_kmxc02_init(const machine_t *);
extern int machine_at_deskmaster286_init(const machine_t *);
extern int machine_at_dells200_init(const machine_t *);
extern int machine_at_tuliptc7_init(const machine_t *);
extern int machine_at_pc8_init(const machine_t *);
extern int machine_at_3302_init(const machine_t *);
@@ -546,6 +548,7 @@ extern int machine_at_exp4349_init(const machine_t *);
extern int machine_at_vect486vl_init(const machine_t *);
extern int machine_at_d824_init(const machine_t *);
extern int machine_at_tuliptc38_init(const machine_t *);
extern int machine_at_martin_init(const machine_t *);
extern int machine_at_403tg_init(const machine_t *);
@@ -610,6 +613,7 @@ extern int machine_at_iach488_init(const machine_t *);
extern int machine_at_pcm9340_init(const machine_t *);
extern int machine_at_pcm5330_init(const machine_t *);
extern int machine_at_84xxuuda_init(const machine_t *);
extern int machine_at_ecs486_init(const machine_t *);
extern int machine_at_hot433a_init(const machine_t *);
extern int machine_at_pl4600c_init(const machine_t *);

View File

@@ -102,4 +102,6 @@ extern int picinterrupt(void);
extern uint8_t pic_irq_ack(void);
extern void pic_toggle_latch(int is_ps2);
#endif /*EMU_PIC_H*/

View File

@@ -24,6 +24,19 @@
#define INT_FIFO_EMP (1 << 3)
#define INT_MASK 0xf
typedef enum {
IBM_8514A_TYPE = 0,
ATI_38800_TYPE,
ATI_68800_TYPE,
TYPE_MAX
} ibm8514_card_type;
typedef enum {
IBM = 0,
ATI,
EXTENSIONS_MAX
} ibm8514_extensions_t;
typedef struct hwcursor8514_t {
int ena;
int x;
@@ -58,7 +71,7 @@ typedef struct ibm8514_t {
int force_old_addr;
int type;
int local;
ibm8514_card_type local;
int bpp;
int on;
int accel_bpp;
@@ -67,7 +80,7 @@ typedef struct ibm8514_t {
uint32_t vram_mask;
uint32_t pallook[512];
uint32_t bios_addr;
uint32_t ma_latch;
uint32_t memaddr_latch;
PALETTE vgapal;
uint8_t hwcursor_oddeven;
@@ -207,8 +220,8 @@ typedef struct ibm8514_t {
int lastline_draw;
int displine;
int fullchange;
uint32_t ma;
uint32_t maback;
uint32_t memaddr;
uint32_t memaddr_backup;
uint8_t *vram;
uint8_t *changedvram;
@@ -223,7 +236,7 @@ typedef struct ibm8514_t {
int hdisp;
int hdisp2;
int hdisped;
int sc;
int scanline;
int vsyncstart;
int vsyncwidth;
int vtotal;
@@ -246,7 +259,8 @@ typedef struct ibm8514_t {
int pitch;
int ext_pitch;
int ext_crt_pitch;
int extensions;
ibm8514_extensions_t extensions;
int onboard;
int linear;
uint32_t vram_amount;
int vram_512k_8514;
@@ -263,9 +277,9 @@ typedef struct ibm8514_t {
} ibm8514_t;
#define IBM_8514A (((dev->local & 0xff) == 0x00) && (dev->extensions == 0x00))
#define ATI_8514A_ULTRA (((dev->local & 0xff) == 0x00) && (dev->extensions == 0x01))
#define ATI_GRAPHICS_ULTRA ((dev->local & 0xff) == 0x01)
#define ATI_MACH32 ((dev->local & 0xff) == 0x02)
#define IBM_8514A (((dev->local & 0xff) == IBM_8514A_TYPE) && (dev->extensions == IBM))
#define ATI_8514A_ULTRA (((dev->local & 0xff) == IBM_8514A_TYPE) && (dev->extensions == ATI))
#define ATI_GRAPHICS_ULTRA ((dev->local & 0xff) == ATI_38800_TYPE)
#define ATI_MACH32 ((dev->local & 0xff) == ATI_68800_TYPE)
#endif /*VIDEO_8514A_H*/

View File

@@ -137,6 +137,7 @@ typedef struct mach_t {
int16_t dx_end;
int16_t dy;
int16_t dy_end;
int16_t dx_first_row_start;
int16_t dx_start;
int16_t dy_start;
int16_t cy;

View File

@@ -11,20 +11,71 @@
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Miran Grca, <mgrca8@gmail.com>,
* Connor Hyde / starfrost, <mario64crashed@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
* Copyright 2025 starfrost (refactoring)
*/
#ifndef VIDEO_CGA_H
#define VIDEO_CGA_H
// Mode flags for the CGA.
// Set by writing to 3D8
typedef enum cga_mode_flags_e
{
CGA_MODE_FLAG_HIGHRES = 1 << 0, // 80-column text mode
CGA_MODE_FLAG_GRAPHICS = 1 << 1, // Graphics mode
CGA_MODE_FLAG_BW = 1 << 2, // Black and white
CGA_MODE_FLAG_VIDEO_ENABLE = 1 << 3, // 0 = no video (as if the video was 0)
CGA_MODE_FLAG_HIGHRES_GRAPHICS = 1 << 4, // 640*200 mode. Corrupts text mode if CGA_MODE_FLAG_GRAPHICS not set.
CGA_MODE_FLAG_BLINK = 1 << 5, // If this is set, bit 5 of textmode characters blinks. Otherwise it is a high-intensity bg mode.
} cga_mode_flags;
// Motorola MC6845 CRTC registers
typedef enum cga_crtc_registers_e
{
CGA_CRTC_HTOTAL = 0x0, // Horizontal total (total number of characters incl. hsync)
CGA_CRTC_HDISP = 0x1, // Horizontal display
CGA_CRTC_HSYNC_POS = 0x2, // Horizontal position of horizontal ysnc
CGA_CRTC_HSYNC_WIDTH = 0x3, // Width of horizontal sync
CGA_CRTC_VTOTAL = 0x4, // Vertical total (total number of scanlines incl. vsync)
CGA_CRTC_VTOTAL_ADJUST = 0x5, // Vertical total adjust value
CGA_CRTC_VDISP = 0x6, // Vertical display (total number of displayed scanline)
CGA_CRTC_VSYNC = 0x7, // Vertical sync scanline number
CGA_CRTC_INTERLACE = 0x8, // Interlacing mode
CGA_CRTC_MAX_SCANLINE_ADDR = 0x9, // Maximum scanline address
CGA_CRTC_CURSOR_START = 0xA, // Cursor start scanline
CGA_CRTC_CURSOR_END = 0xB, // Cursor end scanline
CGA_CRTC_START_ADDR_HIGH = 0xC, // Screen start address high 8 bits
CGA_CRTC_START_ADDR_LOW = 0xD, // Screen start address low 8 bits
CGA_CRTC_CURSOR_ADDR_HIGH = 0xE, // Cursor address high 8 bits
CGA_CRTC_CURSOR_ADDR_LOW = 0xF, // Cursor address low 8 bits
CGA_CRTC_LIGHT_PEN_ADDR_HIGH = 0x10, // Light pen address high 8 bits (not currently supported)
CGA_CRTC_LIGHT_PEN_ADDR_LOW = 0x11, // Light pen address low 8 bits (not currently supported)
} cga_crtc_registers;
// Registers for the CGA
typedef enum cga_registers_e
{
CGA_REGISTER_CRTC_INDEX = 0x3D4,
CGA_REGISTER_CRTC_DATA = 0x3D5,
CGA_REGISTER_MODE_CONTROL = 0x3D8,
CGA_REGISTER_COLOR_SELECT = 0x3D9,
CGA_REGISTER_STATUS = 0x3DA,
CGA_REGISTER_CLEAR_LIGHT_PEN_LATCH = 0x3DB,
CGA_REGISTER_SET_LIGHT_PEN_LATCH = 0x3DC,
} cga_registers;
#define CGA_NUM_CRTC_REGS 32
typedef struct cga_t {
mem_mapping_t mapping;
int crtcreg;
uint8_t crtc[32];
uint8_t crtc[CGA_NUM_CRTC_REGS];
uint8_t cgastat;
@@ -36,17 +87,16 @@ typedef struct cga_t {
int fontbase;
int linepos;
int displine;
int sc;
int scanline;
int vc;
int cgadispon;
int con;
int coff;
int cursorvisible; // Determines if the cursor is visible FOR THE CURRENT SCANLINE.
int cursoron;
int cgablink;
int vsynctime;
int vadj;
uint16_t ma;
uint16_t maback;
uint16_t memaddr;
uint16_t memaddr_backup;
int oddeven;
uint64_t dispontime;

View File

@@ -39,7 +39,7 @@ typedef struct ega_t {
uint8_t lb;
uint8_t lc;
uint8_t ld;
uint8_t stat;
uint8_t status;
uint8_t colourcompare;
uint8_t colournocare;
uint8_t scrblank;
@@ -68,12 +68,12 @@ typedef struct ega_t {
int chain4;
int chain2_read;
int chain2_write;
int con;
int cursorvisible;
int oddeven_page;
int oddeven_chain;
int vc;
int real_vc;
int sc;
int scanline;
int dispon;
int hdisp_on;
int cursoron;
@@ -115,14 +115,14 @@ typedef struct ega_t {
int chipset;
int mono_display;
int mdacols[256][2][2];
int mda_attr_to_color_table[256][2][2];
uint32_t charseta;
uint32_t charsetb;
uint32_t ma_latch;
uint32_t ma;
uint32_t maback;
uint32_t ca;
uint32_t memaddr_latch;
uint32_t memaddr;
uint32_t memaddr_backup;
uint32_t cursoraddr;
uint32_t vram_limit;
uint32_t overscan_color;
uint32_t cca;
@@ -189,11 +189,11 @@ extern void ega_set_type(void *priv, uint32_t local);
extern int firstline_draw;
extern int lastline_draw;
extern int displine;
extern int sc;
extern int scanline;
extern uint32_t ma;
extern uint32_t ca;
extern int con;
extern uint32_t memaddr;
extern uint32_t cursoraddr;
extern int cursorvisible;
extern int cursoron;
extern int cgablink;

View File

@@ -33,9 +33,9 @@
} \
\
if (nr & VAR_ROW0_MA13) \
out_addr = (out_addr & ~0x8000) | ((ega->sc & 1) ? 0x8000 : 0); \
out_addr = (out_addr & ~0x8000) | ((ega->scanline & 1) ? 0x8000 : 0); \
if (nr & VAR_ROW1_MA14) \
out_addr = (out_addr & ~0x10000) | ((ega->sc & 2) ? 0x10000 : 0); \
out_addr = (out_addr & ~0x10000) | ((ega->scanline & 2) ? 0x10000 : 0); \
\
return out_addr; \
}

View File

@@ -13,10 +13,12 @@
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Connor Hyde / starfrost, <mario64crashed@gmail.com
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
* Copyright 2021 Jasmine Iwanek.
* Copyright 2025 starfrost
*/
#ifndef VIDEO_HERCULES_H
@@ -31,7 +33,7 @@ typedef struct {
uint8_t ctrl;
uint8_t ctrl2;
uint8_t stat;
uint8_t status;
uint64_t dispontime;
uint64_t dispofftime;
@@ -43,21 +45,20 @@ typedef struct {
int linepos;
int displine;
int vc;
int sc;
uint16_t ma;
uint16_t maback;
int con;
int coff;
int scanline;
uint16_t memaddr;
uint16_t memaddr_backup;
int cursorvisible;
int cursoron;
int dispon;
int blink;
int vsynctime;
int vadj;
int lp_ff;
int fullchange;
int lp_ff;
int fullchange;
int cols[256][2][2];
int cols[256][2][2];
uint8_t *vram;
int monitor_index;

View File

@@ -1,42 +1,123 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the IBM Monochrome Display and Printer card.
*
* Authors: Sarah Walker, starfrost
*
* Copyright 2007-2024 Sarah Walker
* Copyright 2025 Connor Hyde / starfrost, <mario64crashed@gmail.com>
*/
#ifndef VIDEO_MDA_H
#define VIDEO_MDA_H
// Defines
#define MDA_CRTC_NUM_REGISTERS 32
// Enums & structures
typedef enum mda_registers_e
{
MDA_REGISTER_START = 0x3B0,
MDA_REGISTER_CRTC_INDEX = 0x3B4,
MDA_REGISTER_CRTC_DATA = 0x3B5,
MDA_REGISTER_MODE_CONTROL = 0x3B8,
MDA_REGISTER_CRT_STATUS = 0x3BA,
MDA_REGISTER_PARALLEL_DATA = 0x3BC,
MDA_REGISTER_PRINTER_STATUS = 0x3BD,
MDA_REGISTER_PRINTER_CONTROL = 0x3BE,
MDA_REGISTER_END = 0x3BF,
} mda_registers;
// Motorola MC6845 CRTC registers (without light pen for some reason)
typedef enum mda_crtc_registers_e
{
MDA_CRTC_HTOTAL = 0x0, // Horizontal total (total number of characters incl. hsync)
MDA_CRTC_HDISP = 0x1, // Horizontal display
MDA_CRTC_HSYNC_POS = 0x2, // Horizontal position of horizontal ysnc
MDA_CRTC_HSYNC_WIDTH = 0x3, // Width of horizontal sync
MDA_CRTC_VTOTAL = 0x4, // Vertical total (total number of scanlines incl. vsync)
MDA_CRTC_VTOTAL_ADJUST = 0x5, // Vertical total adjust value
MDA_CRTC_VDISP = 0x6, // Vertical display (total number of displayed scanline)
MDA_CRTC_VSYNC = 0x7, // Vertical sync scanline number
MDA_CRTC_INTERLACE = 0x8, // Interlacing mode
MDA_CRTC_MAX_SCANLINE_ADDR = 0x9, // Maximum scanline address
MDA_CRTC_CURSOR_START = 0xA, // Cursor start scanline
MDA_CRTC_CURSOR_END = 0xB, // Cursor end scanline
MDA_CRTC_START_ADDR_HIGH = 0xC, // Screen start address high 8 bits
MDA_CRTC_START_ADDR_LOW = 0xD, // Screen start address low 8 bits
MDA_CRTC_CURSOR_ADDR_HIGH = 0xE, // Cursor address high 8 bits
MDA_CRTC_CURSOR_ADDR_LOW = 0xF, // Cursor address low 8 bits
} mda_crtc_registers;
typedef enum mda_mode_flags_e
{
MDA_MODE_HIGHRES = 1 << 0, // MUST be enabled for sane operation
MDA_MODE_BW = 1 << 1, // UNUSED in most cases. Not present on Hercules
MDA_MODE_VIDEO_ENABLE = 1 << 3,
MDA_MODE_BLINK = 1 << 5,
} mda_mode_flags;
typedef enum mda_colors_e
{
MDA_COLOR_BLACK = 0,
MDA_COLOR_BLUE = 1,
MDA_COLOR_GREEN = 2,
MDA_COLOR_CYAN = 3,
MDA_COLOR_RED = 4,
MDA_COLOR_MAGENTA = 5,
MDA_COLOR_BROWN = 6,
MDA_COLOR_WHITE = 7,
MDA_COLOR_GREY = 8,
MDA_COLOR_BRIGHT_BLUE = 9,
MDA_COLOR_BRIGHT_GREEN = 10,
MDA_COLOR_BRIGHT_CYAN = 11,
MDA_COLOR_BRIGHT_RED = 12,
MDA_COLOR_BRIGHT_MAGENTA = 13,
MDA_COLOR_BRIGHT_YELLOW = 14,
MDA_COLOR_BRIGHT_WHITE = 15,
} mda_colors;
typedef struct mda_t {
mem_mapping_t mapping;
uint8_t crtc[32];
int crtcreg;
uint8_t crtc[MDA_CRTC_NUM_REGISTERS];
int32_t crtcreg;
uint8_t ctrl;
uint8_t stat;
uint8_t mode;
uint8_t status;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int32_t firstline;
int32_t lastline;
int fontbase;
int linepos;
int displine;
int vc;
int sc;
uint16_t ma;
uint16_t maback;
int con;
int coff;
int cursoron;
int dispon;
int blink;
int vsynctime;
int vadj;
int monitor_index;
int prev_monitor_index;
int32_t fontbase;
int32_t linepos;
int32_t displine;
int32_t vc;
int32_t scanline;
uint16_t memaddr;
uint16_t memaddr_backup;
int32_t cursorvisible;
int32_t cursoron;
int32_t dispon;
int32_t blink;
int32_t vsynctime;
int32_t vadj;
int32_t monitor_index;
int32_t prev_monitor_index;
int32_t monitor_type; // Used for MDA Colour support (REV0 u64)
uint8_t *vram;
} mda_t;

View File

@@ -115,14 +115,13 @@ typedef struct pgc {
int displine;
int vc;
int cgadispon;
int con;
int coff;
int cursorvisible;
int cursoron;
int cgablink;
int vsynctime;
int vadj;
uint16_t ma;
uint16_t maback;
uint16_t memaddr;
uint16_t memaddr_backup;
int oddeven;
uint64_t dispontime;

View File

@@ -100,12 +100,12 @@ typedef struct svga_t {
int dispon;
int hdisp_on;
int vc;
int sc;
int scanline;
int linepos;
int vslines;
int linecountff;
int oddeven;
int con;
int cursorvisible;
int cursoron;
int blink;
int scrollcache;
@@ -152,15 +152,15 @@ typedef struct svga_t {
uint32_t charseta;
uint32_t charsetb;
uint32_t adv_flags;
uint32_t ma_latch;
uint32_t memaddr_latch;
uint32_t ca_adj;
uint32_t ma;
uint32_t maback;
uint32_t memaddr;
uint32_t memaddr_backup;
uint32_t write_bank;
uint32_t read_bank;
uint32_t extra_banks[2];
uint32_t banked_mask;
uint32_t ca;
uint32_t cursoraddr;
uint32_t overscan_color;
uint32_t *map8;
uint32_t pallook[512];

View File

@@ -23,11 +23,11 @@
extern int firstline_draw;
extern int lastline_draw;
extern int displine;
extern int sc;
extern int scanline;
extern uint32_t ma;
extern uint32_t ca;
extern int con;
extern uint32_t memaddr;
extern uint32_t cursoraddr;
extern int cursorvisible;
extern int cursoron;
extern int cgablink;

View File

@@ -47,9 +47,9 @@
} \
\
if (nr & VAR_ROW0_MA13) \
out_addr = (out_addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); \
out_addr = (out_addr & ~0x8000) | ((svga->scanline & 1) ? 0x8000 : 0); \
if (nr & VAR_ROW1_MA14) \
out_addr = (out_addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); \
out_addr = (out_addr & ~0x10000) | ((svga->scanline & 2) ? 0x10000 : 0); \
\
return out_addr; \
}

View File

@@ -127,7 +127,7 @@ typedef struct xga_t {
int dispon;
int h_disp_on;
int vc;
int sc;
int scanline;
int linepos;
int oddeven;
int firstline;
@@ -160,12 +160,12 @@ typedef struct xga_t {
uint32_t hwc_color0;
uint32_t hwc_color1;
uint32_t disp_start_addr;
uint32_t ma_latch;
uint32_t memaddr_latch;
uint32_t vram_size;
uint32_t vram_mask;
uint32_t rom_addr;
uint32_t ma;
uint32_t maback;
uint32_t memaddr;
uint32_t memaddr_backup;
uint32_t read_bank;
uint32_t write_bank;
uint32_t px_map_base;

View File

@@ -187,6 +187,10 @@ extern bitmap_t *buffer32;
#define efscrnsz_y (monitors[monitor_index_global].mon_efscrnsz_y)
#define unscaled_size_x (monitors[monitor_index_global].mon_unscaled_size_x)
#define unscaled_size_y (monitors[monitor_index_global].mon_unscaled_size_y)
#define CGAPAL_CGA_START 16 // Where the 16-color cga text/composite starts
extern PALETTE cgapal;
extern PALETTE cgapal_mono[6];
#if 0
@@ -395,6 +399,7 @@ extern const device_t gd5480_pci_device;
/* Compaq CGA */
extern const device_t compaq_cga_device;
extern const device_t compaq_cga_2_device;
extern const device_t compaq_plasma_device;
/* Olivetti OGC */
extern const device_t ogc_device;
@@ -609,6 +614,11 @@ extern const device_t velocity_200_agp_device;
/* Wyse 700 */
extern const device_t wy700_device;
/* Tandy */
extern const device_t tandy_1000_video_device;
extern const device_t tandy_1000hx_video_device;
extern const device_t tandy_1000sl_video_device;
#endif
#endif /*EMU_VIDEO_H*/

View File

@@ -23,7 +23,6 @@ add_library(mch OBJECT
m_xt_laserxt.c
m_xt_philips.c
m_xt_t1000.c
m_xt_t1000_vid.c
m_xt_xi8088.c
m_xt_zenith.c
m_pcjr.c
@@ -37,7 +36,6 @@ add_library(mch OBJECT
m_at_commodore.c
m_at_grid.c
m_at_t3100e.c
m_at_t3100e_vid.c
m_ps1.c
m_ps1_hdc.c
m_ps2_isa.c

View File

@@ -105,7 +105,7 @@ typedef struct amsvid_t {
int cga_enabled; /* 1640 */
uint8_t cgacol;
uint8_t cgamode;
uint8_t stat;
uint8_t status;
uint8_t plane_write; /* 1512/200 */
uint8_t plane_read; /* 1512/200 */
uint8_t border; /* 1512/200 */
@@ -113,18 +113,17 @@ typedef struct amsvid_t {
int fontbase; /* 1512/200 */
int linepos;
int displine;
int sc;
int scanline;
int vc;
int cgadispon;
int con;
int coff;
int cursorvisible;
int cursoron;
int cgablink;
int vsynctime;
int fullchange;
int vadj;
uint16_t ma;
uint16_t maback;
uint16_t memaddr;
uint16_t memaddr_backup;
int dispon;
int blink;
uint64_t dispontime; /* 1512/1640 */
@@ -291,7 +290,7 @@ vid_in_1512(uint16_t addr, void *priv)
break;
case 0x03da:
ret = vid->stat;
ret = vid->status;
break;
default:
@@ -340,7 +339,7 @@ static void
vid_poll_1512(void *priv)
{
amsvid_t *vid = (amsvid_t *) priv;
uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
@@ -354,13 +353,13 @@ vid_poll_1512(void *priv)
uint16_t dat4;
int cols[4];
int col;
int oldsc;
int scanline_old;
if (!vid->linepos) {
timer_advance_u64(&vid->timer, vid->dispofftime);
vid->stat |= 1;
vid->status |= 1;
vid->linepos = 1;
oldsc = vid->sc;
scanline_old = vid->scanline;
if (vid->dispon) {
if (vid->displine < vid->firstline) {
vid->firstline = vid->displine;
@@ -370,26 +369,26 @@ vid_poll_1512(void *priv)
for (c = 0; c < 8; c++) {
if ((vid->cgamode & 0x12) == 0x12) {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->border & 15) + 16;
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0;
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0;
}
} else {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->cgacol & 15) + 16;
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->cgacol & 15) + 16;
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->cgacol & 15) + 16;
}
}
}
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
for (x = 0; x < 80; x++) {
chr = vid->vram[(vid->ma << 1) & 0x3fff];
attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->cgamode & 0x20) {
chr = vid->vram[(vid->memaddr<< 1) & 0x3fff];
attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff];
drawcursor = ((vid->memaddr== cursoraddr) && vid->cursorvisible && vid->cursoron);
if (vid->cgamode & CGA_MODE_FLAG_BLINK) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((vid->blink & 16) && (attr & 0x80) && !drawcursor)
@@ -400,21 +399,23 @@ vid_poll_1512(void *priv)
}
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
vid->ma++;
vid->memaddr++;
}
} else if (!(vid->cgamode & 2)) {
} else if (!(vid->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
for (x = 0; x < 40; x++) {
chr = vid->vram[(vid->ma << 1) & 0x3fff];
attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->cgamode & 0x20) {
chr = vid->vram[(vid->memaddr<< 1) & 0x3fff];
attr = vid->vram[((vid->memaddr<< 1) + 1) & 0x3fff];
drawcursor = ((vid->memaddr == cursoraddr)
&& vid->cursorvisible && vid->cursoron);
if (vid->cgamode & CGA_MODE_FLAG_BLINK) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if ((vid->blink & 16) && (attr & 0x80))
@@ -423,21 +424,21 @@ vid_poll_1512(void *priv)
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
vid->ma++;
vid->memaddr++;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[vid->fontbase + chr][vid->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
} else if (!(vid->cgamode & 16)) {
} else if (!(vid->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
cols[0] = (vid->cgacol & 15) | 16;
col = (vid->cgacol & 16) ? 24 : 16;
if (vid->cgamode & 4) {
if (vid->cgamode & CGA_MODE_FLAG_BW) {
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
@@ -451,8 +452,8 @@ vid_poll_1512(void *priv)
cols[3] = col | 6;
}
for (x = 0; x < 40; x++) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1];
vid->ma++;
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[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
@@ -460,13 +461,13 @@ vid_poll_1512(void *priv)
}
} else {
for (x = 0; x < 40; x++) {
ca = ((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000);
dat = (vid->vram[ca] << 8) | vid->vram[ca + 1];
dat2 = (vid->vram[ca + 0x4000] << 8) | vid->vram[ca + 0x4001];
dat3 = (vid->vram[ca + 0x8000] << 8) | vid->vram[ca + 0x8001];
dat4 = (vid->vram[ca + 0xc000] << 8) | vid->vram[ca + 0xc001];
cursoraddr = ((vid->memaddr<< 1) & 0x1fff) + ((vid->scanline & 1) * 0x2000);
dat = (vid->vram[cursoraddr] << 8) | vid->vram[cursoraddr + 1];
dat2 = (vid->vram[cursoraddr + 0x4000] << 8) | vid->vram[cursoraddr + 0x4001];
dat3 = (vid->vram[cursoraddr + 0x8000] << 8) | vid->vram[cursoraddr + 0x8001];
dat4 = (vid->vram[cursoraddr + 0xc000] << 8) | vid->vram[cursoraddr + 0xc001];
vid->ma++;
vid->memaddr++;
for (c = 0; c < 16; c++) {
buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16;
dat <<= 1;
@@ -478,7 +479,7 @@ vid_poll_1512(void *priv)
}
} else {
cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16;
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]);
} else {
@@ -487,7 +488,7 @@ vid_poll_1512(void *priv)
}
}
if (vid->cgamode & 1)
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (vid->crtc[1] << 3) + 16;
else
x = (vid->crtc[1] << 4) + 16;
@@ -495,9 +496,9 @@ vid_poll_1512(void *priv)
video_process_8(x, vid->displine << 1);
video_process_8(x, (vid->displine << 1) + 1);
vid->sc = oldsc;
vid->scanline = scanline_old;
if (vid->vsynctime)
vid->stat |= 8;
vid->status |= 8;
vid->displine++;
if (vid->displine >= 360)
vid->displine = 0;
@@ -506,30 +507,29 @@ vid_poll_1512(void *priv)
if ((vid->lastline - vid->firstline) == 199)
vid->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/
if (vid->dispon)
vid->stat &= ~1;
vid->status &= ~1;
vid->linepos = 0;
if (vid->vsynctime) {
vid->vsynctime--;
if (!vid->vsynctime)
vid->stat &= ~8;
vid->status &= ~8;
}
if (vid->sc == (vid->crtc[11] & 31)) {
vid->con = 0;
vid->coff = 1;
if (vid->scanline == (vid->crtc[11] & 31)) {
vid->cursorvisible = 0;
}
if (vid->vadj) {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
vid->scanline++;
vid->scanline &= 31;
vid->memaddr= vid->memaddr_backup;
vid->vadj--;
if (!vid->vadj) {
vid->dispon = 1;
vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff;
vid->sc = 0;
vid->memaddr= vid->memaddr_backup = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff;
vid->scanline = 0;
}
} else if (vid->sc == vid->crtc[9]) {
vid->maback = vid->ma;
vid->sc = 0;
} else if (vid->scanline == vid->crtc[9]) {
vid->memaddr_backup = vid->memaddr;
vid->scanline = 0;
vid->vc++;
vid->vc &= 127;
@@ -547,7 +547,7 @@ vid_poll_1512(void *priv)
vid->displine = 0;
vid->vsynctime = 46;
if (vid->cgamode & 1)
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (vid->crtc[1] << 3) + 16;
else
x = (vid->crtc[1] << 4) + 16;
@@ -584,15 +584,15 @@ vid_poll_1512(void *priv)
video_res_x = xsize;
video_res_y = ysize;
if (vid->cgamode & 1) {
if (vid->cgamode & CGA_MODE_FLAG_HIGHRES) {
video_res_x /= 8;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (!(vid->cgamode & 2)) {
} else if (!(vid->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
video_res_x /= 16;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (!(vid->cgamode & 16)) {
} else if (!(vid->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
video_res_x /= 2;
video_bpp = 2;
} else {
@@ -604,12 +604,12 @@ vid_poll_1512(void *priv)
vid->blink++;
}
} else {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
vid->scanline++;
vid->scanline &= 31;
vid->memaddr= vid->memaddr_backup;
}
if (vid->sc == (vid->crtc[10] & 31))
vid->con = 1;
if (vid->scanline == (vid->crtc[10] & 31))
vid->cursorvisible = 1;
}
}
@@ -1046,7 +1046,7 @@ vid_in_200(uint16_t addr, void *priv)
switch (addr) {
case 0x03b8:
return (mda->ctrl);
return (mda->mode);
case 0x03d8:
return (cga->cgamode);
@@ -1108,9 +1108,9 @@ vid_out_200(uint16_t addr, uint8_t val, void *priv)
}
return;
case 0x3b8:
old = mda->ctrl;
mda->ctrl = val;
if ((mda->ctrl ^ old) & 3)
old = mda->mode;
mda->mode = val;
if ((mda->mode ^ old) & 3)
mda_recalctimings(mda);
vid->crtc_index &= 0x1F;
vid->crtc_index |= 0x80;
@@ -1212,11 +1212,11 @@ vid_out_200(uint16_t addr, uint8_t val, void *priv)
static void
lcd_draw_char_80(amsvid_t *vid, uint32_t *buffer, uint8_t chr,
uint8_t attr, int drawcursor, int blink, int sc,
uint8_t attr, int drawcursor, int blink, int scanline,
int mode160, uint8_t control)
{
int c;
uint8_t bits = fontdat[chr + vid->cga.fontbase][sc];
uint8_t bits = fontdat[chr + vid->cga.fontbase][scanline];
uint8_t bright = 0;
uint16_t mask;
@@ -1247,10 +1247,10 @@ lcd_draw_char_80(amsvid_t *vid, uint32_t *buffer, uint8_t chr,
static void
lcd_draw_char_40(amsvid_t *vid, uint32_t *buffer, uint8_t chr,
uint8_t attr, int drawcursor, int blink, int sc,
uint8_t attr, int drawcursor, int blink, int scanline,
uint8_t control)
{
uint8_t bits = fontdat[chr + vid->cga.fontbase][sc];
uint8_t bits = fontdat[chr + vid->cga.fontbase][scanline];
uint8_t mask = 0x80;
if (attr & 8) /* bright */
@@ -1271,92 +1271,91 @@ static void
lcdm_poll(amsvid_t *vid)
{
mda_t *mda = &vid->mda;
uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
int drawcursor;
int x;
int oldvc;
uint8_t chr;
uint8_t attr;
int oldsc;
int scanline_old;
int blink;
if (!mda->linepos) {
timer_advance_u64(&vid->timer, mda->dispofftime);
mda->stat |= 1;
mda->status |= 1;
mda->linepos = 1;
oldsc = mda->sc;
if ((mda->crtc[8] & 3) == 3)
mda->sc = (mda->sc << 1) & 7;
scanline_old = mda->scanline;
if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3)
mda->scanline = (mda->scanline << 1) & 7;
if (mda->dispon) {
if (mda->displine < mda->firstline)
mda->firstline = mda->displine;
mda->lastline = mda->displine;
for (x = 0; x < mda->crtc[1]; x++) {
chr = mda->vram[(mda->ma << 1) & 0xfff];
attr = mda->vram[((mda->ma << 1) + 1) & 0xfff];
drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron);
blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
for (x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) {
chr = mda->vram[(mda->memaddr<< 1) & 0xfff];
attr = mda->vram[((mda->memaddr<< 1) + 1) & 0xfff];
drawcursor = ((mda->memaddr== cursoraddr) && mda->cursorvisible && mda->cursoron);
blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor);
lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->sc, 0, mda->ctrl);
mda->ma++;
lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->scanline, 0, mda->mode);
mda->memaddr++;
}
}
mda->sc = oldsc;
if (mda->vc == mda->crtc[7] && !mda->sc)
mda->stat |= 8;
mda->scanline = scanline_old;
if (mda->vc == mda->crtc[MDA_CRTC_VSYNC] && !mda->scanline)
mda->status |= 8;
mda->displine++;
if (mda->displine >= 500)
mda->displine = 0;
} else {
timer_advance_u64(&vid->timer, mda->dispontime);
if (mda->dispon)
mda->stat &= ~1;
mda->status &= ~1;
mda->linepos = 0;
if (mda->vsynctime) {
mda->vsynctime--;
if (!mda->vsynctime)
mda->stat &= ~8;
mda->status &= ~8;
}
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) {
mda->con = 0;
mda->coff = 1;
if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31) || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) {
mda->cursorvisible = 0;
}
if (mda->vadj) {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->scanline++;
mda->scanline &= 31;
mda->memaddr= mda->memaddr_backup;
mda->vadj--;
if (!mda->vadj) {
mda->dispon = 1;
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
mda->sc = 0;
mda->memaddr= mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
mda->scanline = 0;
}
} else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) {
mda->maback = mda->ma;
mda->sc = 0;
} else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) {
mda->memaddr_backup = mda->memaddr;
mda->scanline = 0;
oldvc = mda->vc;
mda->vc++;
mda->vc &= 127;
if (mda->vc == mda->crtc[6])
if (mda->vc == mda->crtc[MDA_CRTC_VDISP])
mda->dispon = 0;
if (oldvc == mda->crtc[4]) {
if (oldvc == mda->crtc[MDA_CRTC_VTOTAL]) {
mda->vc = 0;
mda->vadj = mda->crtc[5];
mda->vadj = mda->crtc[MDA_CRTC_VTOTAL_ADJUST];
if (!mda->vadj)
mda->dispon = 1;
if (!mda->vadj)
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
if ((mda->crtc[10] & 0x60) == 0x20)
mda->memaddr= mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
if ((mda->crtc[MDA_CRTC_CURSOR_START] & 0x60) == 0x20)
mda->cursoron = 0;
else
mda->cursoron = mda->blink & 16;
}
if (mda->vc == mda->crtc[7]) {
if (mda->vc == mda->crtc[MDA_CRTC_VSYNC]) {
mda->dispon = 0;
mda->displine = 0;
mda->vsynctime = 16;
if (mda->crtc[7]) {
x = mda->crtc[1] * 8;
if (mda->crtc[MDA_CRTC_VSYNC]) {
x = mda->crtc[MDA_CRTC_HDISP] * 8;
mda->lastline++;
if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) {
xsize = x;
@@ -1372,8 +1371,8 @@ lcdm_poll(amsvid_t *vid)
}
video_blit_memtoscreen(0, mda->firstline, xsize, ysize);
frames++;
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];
video_res_x = mda->crtc[MDA_CRTC_HDISP];
video_res_y = mda->crtc[MDA_CRTC_VDISP];
video_bpp = 0;
}
mda->firstline = 1000;
@@ -1381,12 +1380,12 @@ lcdm_poll(amsvid_t *vid)
mda->blink++;
}
} else {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->scanline++;
mda->scanline &= 31;
mda->memaddr= mda->memaddr_backup;
}
if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1)))
mda->con = 1;
if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31) || ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3 && mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1)))
mda->cursorvisible = 1;
}
}
@@ -1402,19 +1401,19 @@ lcdc_poll(amsvid_t *vid)
uint8_t chr;
uint8_t attr;
uint16_t dat;
int oldsc;
uint16_t ca;
int scanline_old;
uint16_t cursoraddr;
int blink;
ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
cursoraddr = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
if (!cga->linepos) {
timer_advance_u64(&vid->timer, cga->dispofftime);
cga->cgastat |= 1;
cga->linepos = 1;
oldsc = cga->sc;
if ((cga->crtc[8] & 3) == 3)
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
scanline_old = cga->scanline;
if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3)
cga->scanline = ((cga->scanline << 1) + cga->oddeven) & 7;
if (cga->cgadispon) {
if (cga->displine < cga->firstline) {
cga->firstline = cga->displine;
@@ -1422,30 +1421,30 @@ lcdc_poll(amsvid_t *vid)
}
cga->lastline = cga->displine;
if (cga->cgamode & 1) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
chr = cga->charbuffer[x << 1];
attr = cga->charbuffer[(x << 1) + 1];
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor);
lcd_draw_char_80(vid, &(buffer32->line[cga->displine << 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode);
lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->sc, cga->cgamode & 0x40, cga->cgamode);
cga->ma++;
drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron);
blink = ((cga->cgablink & 16) && (cga->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
lcd_draw_char_80(vid, &(buffer32->line[cga->displine << 1])[x * 8], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode & 0x40, cga->cgamode);
lcd_draw_char_80(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 8], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode & 0x40, cga->cgamode);
cga->memaddr++;
}
} else if (!(cga->cgamode & 2)) {
for (x = 0; x < cga->crtc[1]; x++) {
chr = cga->vram[(cga->ma << 1) & 0x3fff];
attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff];
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
blink = ((cga->cgablink & 16) && (cga->cgamode & 0x20) && (attr & 0x80) && !drawcursor);
lcd_draw_char_40(vid, &(buffer32->line[cga->displine << 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode);
lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->sc, cga->cgamode);
cga->ma++;
} else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
chr = cga->vram[(cga->memaddr << 1) & 0x3fff];
attr = cga->vram[((cga->memaddr << 1) + 1) & 0x3fff];
drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron);
blink = ((cga->cgablink & 16) && (cga->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
lcd_draw_char_40(vid, &(buffer32->line[cga->displine << 1])[x * 16], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode);
lcd_draw_char_40(vid, &(buffer32->line[(cga->displine << 1) + 1])[x * 16], chr, attr, drawcursor, blink, cga->scanline, cga->cgamode);
cga->memaddr++;
}
} else { /* Graphics mode */
for (x = 0; x < cga->crtc[1]; x++) {
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
cga->ma++;
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
dat = (cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000)] << 8) | cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000) + 1];
cga->memaddr++;
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[cga->displine << 1][(x << 4) + c] = buffer32->line[(cga->displine << 1) + 1][(x << 4) + c] = (dat & 0x8000) ? blue : green;
dat <<= 1;
@@ -1453,22 +1452,22 @@ lcdc_poll(amsvid_t *vid)
}
}
} else {
if (cga->cgamode & 1) {
hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 3), green);
hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 3), green);
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
hline(buffer32, 0, (cga->displine << 1), (cga->crtc[CGA_CRTC_HDISP] << 3), green);
hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[CGA_CRTC_HDISP] << 3), green);
} else {
hline(buffer32, 0, (cga->displine << 1), (cga->crtc[1] << 4), green);
hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[1] << 4), green);
hline(buffer32, 0, (cga->displine << 1), (cga->crtc[CGA_CRTC_HDISP] << 4), green);
hline(buffer32, 0, (cga->displine << 1) + 1, (cga->crtc[CGA_CRTC_HDISP] << 4), green);
}
}
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3);
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (cga->crtc[CGA_CRTC_HDISP] << 3);
else
x = (cga->crtc[1] << 4);
x = (cga->crtc[CGA_CRTC_HDISP] << 4);
cga->sc = oldsc;
if (cga->vc == cga->crtc[7] && !cga->sc)
cga->scanline = scanline_old;
if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->scanline)
cga->cgastat |= 8;
cga->displine++;
if (cga->displine >= 360)
@@ -1481,54 +1480,53 @@ lcdc_poll(amsvid_t *vid)
if (!cga->vsynctime)
cga->cgastat &= ~8;
}
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) {
cga->con = 0;
cga->coff = 1;
if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
cga->cursorvisible = 0;
}
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
cga->maback = cga->ma;
if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
cga->memaddr_backup = cga->memaddr;
if (cga->vadj) {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->scanline++;
cga->scanline &= 31;
cga->memaddr = cga->memaddr_backup;
cga->vadj--;
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
cga->sc = 0;
cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
cga->scanline = 0;
}
} else if (cga->sc == cga->crtc[9]) {
cga->maback = cga->ma;
cga->sc = 0;
} else if (cga->scanline == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) {
cga->memaddr_backup = cga->memaddr;
cga->scanline = 0;
oldvc = cga->vc;
cga->vc++;
cga->vc &= 127;
if (cga->vc == cga->crtc[6])
if (cga->vc == cga->crtc[CGA_CRTC_VDISP])
cga->cgadispon = 0;
if (oldvc == cga->crtc[4]) {
if (oldvc == cga->crtc[CGA_CRTC_VTOTAL]) {
cga->vc = 0;
cga->vadj = cga->crtc[5];
cga->vadj = cga->crtc[CGA_CRTC_VTOTAL_ADJUST];
if (!cga->vadj)
cga->cgadispon = 1;
if (!cga->vadj)
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
if ((cga->crtc[10] & 0x60) == 0x20)
cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
if ((cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20)
cga->cursoron = 0;
else
cga->cursoron = cga->cgablink & 8;
}
if (cga->vc == cga->crtc[7]) {
if (cga->vc == cga->crtc[CGA_CRTC_VSYNC]) {
cga->cgadispon = 0;
cga->displine = 0;
cga->vsynctime = 16;
if (cga->crtc[7]) {
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3);
if (cga->crtc[CGA_CRTC_VSYNC]) {
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (cga->crtc[CGA_CRTC_HDISP] << 3);
else
x = (cga->crtc[1] << 4);
x = (cga->crtc[CGA_CRTC_HDISP] << 4);
cga->lastline++;
xs_temp = x;
@@ -1540,7 +1538,7 @@ lcdc_poll(amsvid_t *vid)
if (ys_temp < 32)
ys_temp = 400;
if ((cga->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
if ((cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize);
@@ -1557,15 +1555,15 @@ lcdc_poll(amsvid_t *vid)
video_res_x = xsize;
video_res_y = ysize;
if (cga->cgamode & 1) {
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
video_res_x /= 8;
video_res_y /= cga->crtc[9] + 1;
video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 2)) {
} else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
video_res_x /= 16;
video_res_y /= cga->crtc[9] + 1;
video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 16)) {
} else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
video_res_x /= 2;
video_bpp = 2;
} else
@@ -1577,17 +1575,17 @@ lcdc_poll(amsvid_t *vid)
cga->oddeven ^= 1;
}
} else {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->scanline++;
cga->scanline &= 31;
cga->memaddr = cga->memaddr_backup;
}
if (cga->cgadispon)
cga->cgastat &= ~1;
if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1)))
cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1)) {
for (x = 0; x < (cga->crtc[1] << 1); x++)
cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff];
if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1)))
cga->cursorvisible = 1;
if (cga->cgadispon && (cga->cgamode & CGA_MODE_FLAG_HIGHRES)) {
for (x = 0; x < (cga->crtc[CGA_CRTC_HDISP] << 1); x++)
cga->charbuffer[x] = cga->vram[((cga->memaddr << 1) + x) & 0x3fff];
}
}
}

View File

@@ -154,32 +154,68 @@ machine_at_ps2_ide_init(const machine_t *model)
static const device_config_t ibmat_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "ibm5170_111585",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "62X082x (11/15/85)", .internal_name = "ibm5170_111585", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47.BIN", "" } },
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{
.name = "62X082x (11/15/85)",
.internal_name = "ibm5170_111585",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47.BIN", "" }
},
{
.name = "61X9266 (11/15/85) (Alt)",
.internal_name = "ibm5170_111585_alt",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27_61X9266.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47_61X9265.BIN", "" }
},
{
.name = "648009x (06/10/85)",
.internal_name = "ibm5170_061085",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmat/BIOS_5170_10JUN85_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JUN85_U47.BIN", "" }
},
{
.name = "618102x (01/10/84)",
.internal_name = "ibm5170_011084",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmat/BIOS_5170_10JAN84_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JAN84_U47.BIN", "" }
},
// The following are Diagnostic ROMs.
{
.name = "Supersoft Diagnostics",
.internal_name = "diag_supersoft",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 2,
.size = 65536,
.files = { "roms/machines/diagnostic/5170_EVEN_LOW_U27_27256.bin", "roms/machines/diagnostic/5170_ODD_HIGH_U47_27256.bin", "" }
},
{ .name = "61X9266 (11/15/85) (Alt)", .internal_name = "ibm5170_111585_alt", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_15NOV85_U27_61X9266.BIN", "roms/machines/ibmat/BIOS_5170_15NOV85_U47_61X9265.BIN", "" } },
{ .name = "648009x (06/10/85)", .internal_name = "ibm5170_061085", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_10JUN85_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JUN85_U47.BIN", "" } },
{ .name = "618102x (01/10/84)", .internal_name = "ibm5170_011084", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmat/BIOS_5170_10JAN84_U27.BIN", "roms/machines/ibmat/BIOS_5170_10JAN84_U47.BIN", "" } },
{ .files_no = 0 }
},
},
{
.name = "enable_5161",
.name = "enable_5161",
.description = "IBM 5161 Expansion Unit",
.type = CONFIG_BINARY,
.type = CONFIG_BINARY,
.default_int = 0
},
{ .name = "", .description = "", .type = CONFIG_END }

View File

@@ -262,6 +262,19 @@ machine_at_px286_init(const machine_t *model)
return ret;
}
static void
machine_at_ctat_common_init(const machine_t *model)
{
machine_at_common_init(model);
device_add(&cs8220_device);
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
device_add(&keyboard_at_phoenix_device);
}
int
machine_at_dells200_init(const machine_t *model)
{
@@ -274,14 +287,24 @@ machine_at_dells200_init(const machine_t *model)
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
machine_at_ctat_common_init(model);
device_add(&cs8220_device);
return ret;
}
if (fdc_current[0] == FDC_INTERNAL)
device_add(&fdc_at_device);
int
machine_at_tuliptc7_init(const machine_t *model)
{
int ret;
device_add(&keyboard_at_phoenix_device);
ret = bios_load_interleavedr("roms/machines/tuliptc7/tc7be.bin",
"roms/machines/tuliptc7/tc7bo.bin",
0x000f8000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_ctat_common_init(model);
return ret;
}
@@ -1105,7 +1128,7 @@ machine_at_3302_init(const machine_t *model)
device_add(&fdc_at_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&paradise_pvga1a_ncr3302_device);
device_add(machine_get_vid_device(machine));
device_add(&keyboard_at_ncr_device);

View File

@@ -413,7 +413,7 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems
return ret;
if (gfxcard[0] == VID_INTERNAL)
device_add(&gd5428_onboard_device);
device_add(machine_get_vid_device(machine));
machine_at_common_init_ex(model, 2);
@@ -439,7 +439,7 @@ machine_at_d824_init(const machine_t *model)
return ret;
if (gfxcard[0] == VID_INTERNAL)
device_add(&gd5428_onboard_device);
device_add(machine_get_vid_device(machine));
machine_at_common_init_ex(model, 2);
@@ -457,6 +457,41 @@ machine_at_d824_init(const machine_t *model)
return ret;
}
int
machine_at_tuliptc38_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/tuliptc38/TULIP1.BIN",
0x000f0000, 262144, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
device_add(&vl82c486_device);
device_add(&tulip_jumper_device);
device_add(&vl82c113_device);
device_add(&ide_isa_device);
device_add(&fdc37c651_ide_device);
if (gfxcard[0] == VID_INTERNAL) {
bios_load_aux_linear("roms/machines/tuliptc38/VBIOS.BIN",
0x000c0000, 32768, 0);
device_add(machine_get_vid_device(machine));
} else for (uint16_t i = 0; i < 32768; i++)
rom[i] = mem_readb_phys(0x000c0000 + i);
mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000);
mem_mapping_set_exec(&bios_mapping, rom);
return ret;
}
int
machine_at_martin_init(const machine_t *model)
{
@@ -2197,18 +2232,66 @@ machine_at_ecs486_init(const machine_t *model)
return ret;
}
static const device_config_t hot433a_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "hot433a",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "AMI", .internal_name = "hot433a", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/hot433/433AUS33.ROM", "" } },
{ .name = "Award (eSupport update)", .internal_name = "hot433a_award", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/hot433/2A4X5H21.BIN", "" } },
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t hot433a_device = {
.name = "Shuttle HOT-433A",
.internal_name = "hot433a_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = hot433a_config
};
int
machine_at_hot433a_init(const machine_t *model)
{
int ret;
int ret = 0;
const char* fn;
ret = bios_load_linear("roms/machines/hot433/433AUS33.ROM",
0x000e0000, 131072, 0);
/* No ROMs available */
if (!device_available(model->device))
return ret;
device_context(model->device);
int is_award = !strcmp(device_get_config_bios("bios"), "hot433a_award");
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();
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
machine_at_common_init_ex(model, 2);
if (is_award)
device_add(&amstrad_megapc_nvr_device);
else
device_add(&ami_1994_nvr_device);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
@@ -2220,9 +2303,46 @@ machine_at_hot433a_init(const machine_t *model)
device_add(&umc_hb4_device);
device_add(&umc_8886bf_device);
device_add(&um8669f_device);
if (is_award)
device_add(&um8663af_device);
else
device_add(&um8669f_device);
device_add(&winbond_flash_w29c010_device);
device_add(&keyboard_at_ami_device);
if (is_award)
device_add(&keyboard_ps2_ami_device);
else
device_add(&keyboard_at_ami_device);
pic_toggle_latch(is_award);
return ret;
}
int
machine_at_84xxuuda_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/84xxuuda/uud0520s.bin",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x12, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2);
device_add(&umc_hb4_device);
device_add(&umc_8886bf_device);
device_add(&um8663bf_device);
device_add(&winbond_flash_w29c010_device);
device_add(&keyboard_ps2_ami_device);
return ret;
}
@@ -2327,7 +2447,7 @@ machine_at_actionpc2600_init(const machine_t *model)
device_add(&keyboard_ps2_tg_ami_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&tgui9440_onboard_pci_device);
device_add(machine_get_vid_device(machine));
return ret;
}
@@ -2359,7 +2479,7 @@ machine_at_actiontower8400_init(const machine_t *model)
device_add(&intel_flash_bxt_device); // The ActionPC 2600 has this so I'm gonna assume this does too.
device_add(&keyboard_ps2_ami_pci_device);
if (gfxcard[0] == VID_INTERNAL)
device_add(&gd5430_onboard_pci_device);
device_add(machine_get_vid_device(machine));
return ret;
}

View File

@@ -44,9 +44,6 @@
#include <86box/vid_cga_comp.h>
#include <86box/plat_unused.h>
static video_timings_t timing_compaq_plasma = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
enum {
COMPAQ_PORTABLEII = 0,
COMPAQ_PORTABLEIII,
@@ -55,752 +52,11 @@ enum {
COMPAQ_DESKPRO386_05_1988
};
#define CGA_RGB 0
#define CGA_COMPOSITE 1
/*Very rough estimate*/
#define VID_CLOCK (double) (651 * 416 * 60)
/* Mapping of attributes to colours */
static uint32_t amber;
static uint32_t black;
static uint32_t blinkcols[256][2];
static uint32_t normcols[256][2];
/* Video options set by the motherboard; they will be picked up by the card
* on the next poll.
*
* Bit 3: Disable built-in video (for add-on card)
* Bit 2: Thin font
* Bits 0,1: Font set (not currently implemented)
*/
static int8_t cpq_st_display_internal = -1;
static uint8_t mdaattr[256][2][2];
static void
compaq_plasma_display_set(uint8_t internal)
{
cpq_st_display_internal = internal;
}
typedef struct compaq_plasma_t {
cga_t cga;
mem_mapping_t font_ram_mapping;
uint8_t *font_ram;
uint8_t port_13c6;
uint8_t port_23c6;
uint8_t port_27c6;
uint8_t internal_monitor;
} compaq_plasma_t;
static int compaq_machine_type = 0;
/* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */
static mem_mapping_t ram_mapping;
static void compaq_plasma_recalcattrs(compaq_plasma_t *self);
static void
compaq_plasma_recalctimings(compaq_plasma_t *self)
{
double _dispontime;
double _dispofftime;
double disptime;
if (!self->internal_monitor && !(self->port_23c6 & 0x01)) {
cga_recalctimings(&self->cga);
return;
}
disptime = 651;
_dispontime = 640;
_dispofftime = disptime - _dispontime;
self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32));
self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32));
}
static void
compaq_plasma_waitstates(UNUSED(void *priv))
{
int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 };
int ws;
ws = ws_array[cycles & 0xf];
sub_cycles(ws);
}
static void
compaq_plasma_write(uint32_t addr, uint8_t val, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
if (self->port_23c6 & 0x08)
self->font_ram[addr & 0x1fff] = val;
else
self->cga.vram[addr & 0x7fff] = val;
compaq_plasma_waitstates(&self->cga);
}
static uint8_t
compaq_plasma_read(uint32_t addr, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t ret;
compaq_plasma_waitstates(&self->cga);
if (self->port_23c6 & 0x08)
ret = (self->font_ram[addr & 0x1fff]);
else
ret = (self->cga.vram[addr & 0x7fff]);
return ret;
}
static void
compaq_plasma_out(uint16_t addr, uint8_t val, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
switch (addr) {
/* Emulated CRTC, register select */
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
cga_out(addr, val, &self->cga);
break;
/* Emulated CRTC, value */
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
cga_out(addr, val, &self->cga);
compaq_plasma_recalctimings(self);
break;
case 0x3d8:
case 0x3d9:
cga_out(addr, val, &self->cga);
break;
case 0x13c6:
self->port_13c6 = val;
compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0);
/*
For bits 2-0, John gives 0 = CGA, 1 = EGA, 3 = MDA;
Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA;
This leads me to believe bit 2 is not relevant to the mode.
*/
if ((val & 0x03) == 0x03)
mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000);
else
mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000);
break;
case 0x23c6:
self->port_23c6 = val;
compaq_plasma_recalcattrs(self);
break;
case 0x27c6:
self->port_27c6 = val;
break;
default:
break;
}
}
static uint8_t
compaq_plasma_in(uint16_t addr, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x3d4:
case 0x3da:
case 0x3db:
case 0x3dc:
ret = cga_in(addr, &self->cga);
break;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
ret = cga_in(addr, &self->cga);
break;
case 0x3d8:
ret = self->cga.cgamode;
break;
case 0x13c6:
ret = self->port_13c6;
#if 0
if ((self->cga.cgamode & 0x28) == 0x00)
ret |= 0x04;
#endif
break;
case 0x17c6:
ret = 0xe6;
break;
case 0x1bc6:
ret = 0x40;
break;
case 0x23c6:
ret = self->port_23c6;
break;
case 0x27c6:
ret = self->port_27c6 & 0x3f;
break;
default:
break;
}
return ret;
}
static void
compaq_plasma_poll(void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t chr;
uint8_t attr;
uint8_t sc;
uint16_t ma = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x7fff;
uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x7fff;
uint16_t addr;
int drawcursor;
int cursorline;
int blink = 0;
int underline = 0;
int c;
int x;
uint32_t ink = 0;
uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black;
uint32_t bg = black;
uint32_t cols[2];
uint8_t dat;
uint8_t pattern;
uint32_t ink0 = 0;
uint32_t ink1 = 0;
/* Switch between internal plasma and external CRT display. */
if ((cpq_st_display_internal != -1) && (cpq_st_display_internal != self->internal_monitor)) {
self->internal_monitor = cpq_st_display_internal;
compaq_plasma_recalctimings(self);
}
/* graphic mode and not mode 40h */
if (!self->internal_monitor && !(self->port_23c6 & 0x01)) {
/* standard cga mode */
cga_poll(&self->cga);
return;
} else {
/* mode 40h or text mode */
if (!self->cga.linepos) {
timer_advance_u64(&self->cga.timer, self->cga.dispofftime);
self->cga.cgastat |= 1;
self->cga.linepos = 1;
if (self->cga.cgadispon) {
if (self->cga.displine == 0)
video_wait_for_buffer();
/* 80-col */
if (self->cga.cgamode & 0x01) {
sc = self->cga.displine & 0x0f;
addr = ((ma & ~1) + (self->cga.displine >> 4) * 80) << 1;
ma += (self->cga.displine >> 4) * 80;
if ((self->cga.crtc[0x0a] & 0x60) == 0x20)
cursorline = 0;
else
cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc);
/* for each text column */
for (x = 0; x < 80; x++) {
/* video output enabled */
if (self->cga.cgamode & 0x08) {
/* character */
chr = self->cga.vram[(addr + (x << 1)) & 0x7fff];
/* text attributes */
attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff];
} else {
chr = 0x00;
attr = 0x00;
}
uint8_t hi_bit = attr & 0x08;
/* check if cursor has to be drawn */
drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10));
/* check if character underline mode should be set */
underline = ((attr & 0x07) == 0x01);
underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit);
if (underline) {
/* set forecolor to white */
attr = attr | 0x7;
}
blink = 0;
/* set foreground */
cols[1] = blinkcols[attr][1];
/* blink active */
if (self->cga.cgamode & 0x20) {
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) {
/* set blinking */
cols[1] = cols[0];
blink = 1;
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character address */
uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff;
if (((self->port_23c6 >> 5) == 3) && hi_bit)
chr_addr |= 0x1000;
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (sc == 7)) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
if (hi_bit) {
if ((self->port_23c6 >> 5) == 1) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] ^= (amber ^ black);
} else if ((self->port_23c6 >> 5) == 4) {
for (c = 0; c < 8; c++) {
uint32_t b = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 1) & 0x7f;
uint32_t g = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 9) & 0x7f;
uint32_t r = ((buffer32->line[self->cga.displine][(x << 3) + c]) >> 17) & 0x7f;
buffer32->line[self->cga.displine][(x << 3) + c] = b | (g << 8) || (r << 16);
}
}
}
ma++;
}
}
/* 40-col */
else if (!(self->cga.cgamode & 0x02)) {
sc = self->cga.displine & 0x0f;
addr = ((ma & ~1) + (self->cga.displine >> 4) * 40) << 1;
ma += (self->cga.displine >> 4) * 40;
if ((self->cga.crtc[0x0a] & 0x60) == 0x20)
cursorline = 0;
else
cursorline = (((self->cga.crtc[0x0a] & 0x0f) << 1) <= sc) && (((self->cga.crtc[0x0b] & 0x0f) << 1) >= sc);
for (x = 0; x < 40; x++) {
/* video output enabled */
if (self->cga.cgamode & 0x08) {
/* character */
chr = self->cga.vram[(addr + (x << 1)) & 0x7fff];
/* text attributes */
attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff];
} else {
chr = 0x00;
attr = 0x00;
}
uint8_t hi_bit = attr & 0x08;
/* check if cursor has to be drawn */
drawcursor = ((ma == ca) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10));
/* check if character underline mode should be set */
underline = ((attr & 0x07) == 0x01);
underline = underline || (((self->port_23c6 >> 5) == 2) && hi_bit);
if (underline) {
/* set forecolor to white */
attr = attr | 0x7;
}
blink = 0;
/* set foreground */
cols[1] = blinkcols[attr][1];
/* blink active */
if (self->cga.cgamode & 0x20) {
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) {
/* set blinking */
cols[1] = cols[0];
blink = 1;
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character address */
uint16_t chr_addr = ((chr * 16) + sc) & 0x0fff;
if (((self->port_23c6 >> 5) == 3) && hi_bit)
chr_addr |= 0x1000;
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (sc == 7)) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
if (hi_bit) {
if ((self->port_23c6 >> 5) == 1)
for (c = 0; c < 8; c++) {
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] ^= (amber ^ black);
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] ^= (amber ^ black);
}
else if ((self->port_23c6 >> 5) == 4)
for (c = 0; c < 8; c++) {
uint32_t b = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 1) & 0x7f;
uint32_t g = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 9) & 0x7f;
uint32_t r = ((buffer32->line[self->cga.displine][(x << 4) + (c << 1)]) >> 17) & 0x7f;
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = b | (g << 8) || (r << 16);
}
}
ma++;
}
} else {
if (self->cga.cgamode & 0x10) {
/* 640x400 mode */
if (self->port_23c6 & 0x01) /* 640*400 */ {
addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
} else {
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
}
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7fff];
addr++;
for (uint8_t c = 0; c < 8; c++) {
ink = (dat & 0x80) ? fg : bg;
if (!(self->cga.cgamode & 0x08))
ink = black;
buffer32->line[self->cga.displine][(x << 3) + c] = ink;
dat <<= 1;
}
}
} else {
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((ma & ~1) << 1);
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7fff];
addr++;
for (uint8_t c = 0; c < 4; c++) {
pattern = (dat & 0xC0) >> 6;
if (!(self->cga.cgamode & 0x08))
pattern = 0;
switch (pattern & 3) {
case 0:
ink0 = ink1 = black;
break;
case 1:
if (self->cga.displine & 0x01) {
ink0 = black;
ink1 = black;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 2:
if (self->cga.displine & 0x01) {
ink0 = black;
ink1 = amber;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 3:
ink0 = ink1 = amber;
break;
default:
break;
}
buffer32->line[self->cga.displine][(x << 3) + (c << 1)] = ink0;
buffer32->line[self->cga.displine][(x << 3) + (c << 1) + 1] = ink1;
dat <<= 2;
}
}
}
}
}
self->cga.displine++;
/* Hardcode a fixed refresh rate and VSYNC timing */
if (self->cga.displine == 400) { /* Start of VSYNC */
self->cga.cgastat |= 8;
self->cga.cgadispon = 0;
}
if (self->cga.displine == 416) { /* End of VSYNC */
self->cga.displine = 0;
self->cga.cgastat &= ~8;
self->cga.cgadispon = 1;
}
} else {
timer_advance_u64(&self->cga.timer, self->cga.dispontime);
if (self->cga.cgadispon)
self->cga.cgastat &= ~1;
self->cga.linepos = 0;
if (self->cga.displine == 400) {
xsize = 640;
ysize = 400;
if ((self->cga.cgamode & 0x08) || video_force_resize_get()) {
set_screen_size(xsize, ysize);
if (video_force_resize_get())
video_force_resize_set(0);
}
/* Plasma specific */
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
/* Fixed 640x400 resolution */
video_res_x = 640;
video_res_y = 400;
if (self->cga.cgamode & 0x02) {
if (self->cga.cgamode & 0x10)
video_bpp = 1;
else
video_bpp = 2;
} else
video_bpp = 0;
self->cga.cgablink++;
}
}
}
}
static void
compaq_plasma_mdaattr_rebuild(void)
{
for (uint16_t c = 0; c < 256; c++) {
mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16;
if (c & 8)
mdaattr[c][0][1] = 15 + 16;
else
mdaattr[c][0][1] = 7 + 16;
}
mdaattr[0x70][0][1] = 16;
mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15;
mdaattr[0xF0][0][1] = 16;
mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15;
mdaattr[0x78][0][1] = 16 + 7;
mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15;
mdaattr[0xF8][0][1] = 16 + 7;
mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15;
mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16;
mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16;
mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16;
mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16;
}
static void
compaq_plasma_recalcattrs(compaq_plasma_t *self)
{
int n;
/* val behaves as follows:
* Bit 0: Attributes 01-06, 08-0E are inverse video
* Bit 1: Attributes 01-06, 08-0E are bold
* Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF
* are inverse video
* Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF
* are bold */
/* Set up colours */
amber = makecol(0xff, 0x7d, 0x00);
black = makecol(0x64, 0x19, 0x00);
/* Initialize the attribute mapping. Start by defaulting everything
* to black on amber, and with bold set by bit 3 */
for (n = 0; n < 256; n++) {
blinkcols[n][0] = normcols[n][0] = amber;
blinkcols[n][1] = normcols[n][1] = black;
}
/* Colours 0x11-0xFF are controlled by bits 2 and 3 of the
* passed value. Exclude x0 and x8, which are always black on
* amber. */
for (n = 0x11; n <= 0xFF; n++) {
if ((n & 7) == 0)
continue;
if ((self->port_23c6 >> 5) == 1) { /* Inverse */
blinkcols[n][0] = normcols[n][0] = amber;
blinkcols[n][1] = normcols[n][1] = black;
} else { /* Normal */
blinkcols[n][0] = normcols[n][0] = black;
blinkcols[n][1] = normcols[n][1] = amber;
}
}
/* Set up the 01-0E range, controlled by bits 0 and 1 of the
* passed value. When blinking is enabled this also affects 81-8E. */
for (n = 0x01; n <= 0x0E; n++) {
if (n == 7)
continue;
if ((self->port_23c6 >> 5) == 1) {
blinkcols[n][0] = normcols[n][0] = amber;
blinkcols[n][1] = normcols[n][1] = black;
blinkcols[n + 128][0] = amber;
blinkcols[n + 128][1] = black;
} else {
blinkcols[n][0] = normcols[n][0] = black;
blinkcols[n][1] = normcols[n][1] = amber;
blinkcols[n + 128][0] = black;
blinkcols[n + 128][1] = amber;
}
}
/* Colours 07 and 0F are always amber on black. If blinking is
* enabled so are 87 and 8F. */
for (n = 0x07; n <= 0x0F; n += 8) {
blinkcols[n][0] = normcols[n][0] = black;
blinkcols[n][1] = normcols[n][1] = amber;
blinkcols[n + 128][0] = black;
blinkcols[n + 128][1] = amber;
}
/* When not blinking, colours 81-8F are always amber on black. */
for (n = 0x81; n <= 0x8F; n++) {
normcols[n][0] = black;
normcols[n][1] = amber;
}
/* Finally do the ones which are solid black. These differ between
* the normal and blinking mappings */
for (n = 0; n <= 0xFF; n += 0x11)
normcols[n][0] = normcols[n][1] = black;
/* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */
for (n = 0; n <= 0x77; n += 0x11) {
blinkcols[n][0] = blinkcols[n][1] = black;
blinkcols[n + 128][0] = blinkcols[n + 128][1] = black;
}
}
static void *
compaq_plasma_init(UNUSED(const device_t *info))
{
compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t));
cga_init(&self->cga);
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma);
self->cga.composite = 0;
self->cga.revision = 0;
self->cga.vram = malloc(0x8000);
self->internal_monitor = 1;
self->font_ram = malloc(0x2000);
cga_comp_init(self->cga.revision);
timer_set_callback(&self->cga.timer, compaq_plasma_poll);
timer_set_p(&self->cga.timer, self);
mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000,
compaq_plasma_read, NULL, NULL,
compaq_plasma_write, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL, self);
for (int i = 1; i <= 2; i++) {
io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
}
io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
overscan_x = overscan_y = 16;
self->cga.rgb_type = device_get_config_int("rgb_type");
cga_palette = (self->cga.rgb_type << 1);
cgapal_rebuild();
compaq_plasma_mdaattr_rebuild();
return self;
}
static void
compaq_plasma_close(void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
free(self->cga.vram);
free(self->font_ram);
free(self);
}
static void
compaq_plasma_speed_changed(void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
compaq_plasma_recalctimings(self);
}
const device_config_t compaq_plasma_config[] = {
// clang-format off
{
.name = "rgb_type",
.description = "RGB type",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "Color", .value = 0 },
{ .description = "Green Monochrome", .value = 1 },
{ .description = "Amber Monochrome", .value = 2 },
{ .description = "Gray Monochrome", .value = 3 },
{ .description = "" }
}
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t compaq_plasma_device = {
.name = "Compaq Plasma",
.internal_name = "compaq_plasma",
.flags = 0,
.local = 0,
.init = compaq_plasma_init,
.close = compaq_plasma_close,
.reset = NULL,
.available = NULL,
.speed_changed = compaq_plasma_speed_changed,
.force_redraw = NULL,
.config = compaq_plasma_config
};
static uint8_t
read_ram(uint32_t addr, UNUSED(void *priv))

View File

@@ -58,13 +58,13 @@ static void
elt_vid_off_poll(void *priv)
{
cga_t *cga = priv;
uint8_t hdisp = cga->crtc[1];
uint8_t hdisp = cga->crtc[CGA_CRTC_HDISP];
/* Don't display anything.
* TODO: Do something less stupid to emulate backlight off. */
cga->crtc[1] = 0;
cga->crtc[CGA_CRTC_HDISP] = 0;
cga_poll(cga);
cga->crtc[1] = hdisp;
cga->crtc[CGA_CRTC_HDISP] = hdisp;
}
static void

View File

@@ -646,6 +646,7 @@ europc_boot(UNUSED(const device_t *info))
* (JS9) can be used to "move" it to 0x0350, to get it out of
* the way of other cards that need this range.
*/
sys->jim = device_get_config_hex16("js9");
io_sethandler(sys->jim, 16,
jim_read, NULL, NULL, jim_write, NULL, NULL, sys);
@@ -680,14 +681,14 @@ static const device_config_t europc_config[] = {
{
.name = "js9",
.description = "JS9 Jumper (JIM)",
.type = CONFIG_INT,
.type = CONFIG_HEX16,
.default_string = "",
.default_int = 0,
.default_int = 0x0250,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "Disabled (250h)", .value = 0 },
{ .description = "Enabled (350h)", .value = 1 },
{ .description = "Disabled (250h)", .value = 0x0250 },
{ .description = "Enabled (350h)", .value = 0x0350 },
{ .description = "" }
},
},

View File

@@ -48,11 +48,10 @@
#include <86box/snd_sn76489.h>
#include <86box/video.h>
#include <86box/vid_cga_comp.h>
#include <86box/m_pcjr.h>
#include <86box/machine.h>
#include <86box/plat_unused.h>
#define PCJR_RGB 0
#define PCJR_COMPOSITE 1
#define STAT_PARITY 0x80
#define STAT_RTIMEOUT 0x40
@@ -63,50 +62,10 @@
#define STAT_IFULL 0x02
#define STAT_OFULL 0x01
typedef struct pcjr_t {
/* Video Controller stuff. */
mem_mapping_t mapping;
uint8_t crtc[32];
int crtcreg;
int array_index;
uint8_t array[32];
int array_ff;
int memctrl;
uint8_t stat;
int addr_mode;
uint8_t *vram;
uint8_t *b8000;
int linepos;
int displine;
int sc;
int vc;
int dispon;
int con;
int coff;
int cursoron;
int blink;
int vsynctime;
int fullchange;
int vadj;
uint16_t ma;
uint16_t maback;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int composite;
int apply_hd;
/* Keyboard Controller stuff. */
int latched;
int data;
int serial_data[44];
int serial_pos;
uint8_t pa;
uint8_t pb;
pc_timer_t send_delay_timer;
} pcjr_t;
static uint8_t key_queue[16];
static int key_queue_start = 0;
static int key_queue_end = 0;
/*PCjr keyboard has no escape scancodes, and no scancodes beyond 54
Map right alt to 54h (FN) */
@@ -627,644 +586,6 @@ const scancode scancode_pcjr[512] = {
// clang-format on
};
static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/
static uint8_t crtcmask[32] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f,
0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static uint8_t key_queue[16];
static int key_queue_start = 0;
static int key_queue_end = 0;
static void
recalc_address(pcjr_t *pcjr)
{
uint8_t masked_memctrl = pcjr->memctrl;
/* According to the Technical Reference, bits 2 and 5 are
ignored if there is only 64k of RAM and there are only
4 pages. */
if (mem_size < 128)
masked_memctrl &= ~0x24;
if ((pcjr->memctrl & 0xc0) == 0xc0) {
pcjr->vram = &ram[(masked_memctrl & 0x06) << 14];
pcjr->b8000 = &ram[(masked_memctrl & 0x30) << 11];
} else {
pcjr->vram = &ram[(masked_memctrl & 0x07) << 14];
pcjr->b8000 = &ram[(masked_memctrl & 0x38) << 11];
}
}
static void
recalc_timings(pcjr_t *pcjr)
{
double _dispontime;
double _dispofftime;
double disptime;
if (pcjr->array[0] & 1) {
disptime = pcjr->crtc[0] + 1;
_dispontime = pcjr->crtc[1];
} else {
disptime = (pcjr->crtc[0] + 1) << 1;
_dispontime = pcjr->crtc[1] << 1;
}
_dispofftime = disptime - _dispontime;
_dispontime *= CGACONST;
_dispofftime *= CGACONST;
pcjr->dispontime = (uint64_t) (_dispontime);
pcjr->dispofftime = (uint64_t) (_dispofftime);
}
static int
vid_get_h_overscan_size(pcjr_t *pcjr)
{
int ret;
if (pcjr->array[0] & 1)
ret = 128;
else
ret = 256;
return ret;
}
static void
vid_out(uint16_t addr, uint8_t val, void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
uint8_t old;
switch (addr) {
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
pcjr->crtcreg = val & 0x1f;
return;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
old = pcjr->crtc[pcjr->crtcreg];
pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg];
if (pcjr->crtcreg == 2)
overscan_x = vid_get_h_overscan_size(pcjr);
if (old != val) {
if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) {
pcjr->fullchange = changeframecount;
recalc_timings(pcjr);
}
}
return;
case 0x3da:
if (!pcjr->array_ff)
pcjr->array_index = val & 0x1f;
else {
if (pcjr->array_index & 0x10)
val &= 0x0f;
pcjr->array[pcjr->array_index & 0x1f] = val;
if (!(pcjr->array_index & 0x1f))
update_cga16_color(val);
}
pcjr->array_ff = !pcjr->array_ff;
break;
case 0x3df:
pcjr->memctrl = val;
pcjr->pa = val; /* The PCjr BIOS expects the value written to 3DF to
then be readable from port 60, others it errors out
with only 64k RAM set (but somehow, still works with
128k or more RAM). */
pcjr->addr_mode = val >> 6;
recalc_address(pcjr);
break;
default:
break;
}
}
static uint8_t
vid_in(uint16_t addr, void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
ret = pcjr->crtcreg;
break;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
ret = pcjr->crtc[pcjr->crtcreg];
break;
case 0x3da:
pcjr->array_ff = 0;
pcjr->stat ^= 0x10;
ret = pcjr->stat;
break;
default:
break;
}
return ret;
}
static void
vid_write(uint32_t addr, uint8_t val, void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
if (pcjr->memctrl == -1)
return;
pcjr->b8000[addr & 0x3fff] = val;
}
static uint8_t
vid_read(uint32_t addr, void *priv)
{
const pcjr_t *pcjr = (pcjr_t *) priv;
if (pcjr->memctrl == -1)
return 0xff;
return (pcjr->b8000[addr & 0x3fff]);
}
static int
vid_get_h_overscan_delta(pcjr_t *pcjr)
{
int def;
int coef;
int ret;
switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) {
case 0x13: /*320x200x16*/
def = 0x56;
coef = 8;
break;
case 0x12: /*160x200x16*/
def = 0x2c; /* I'm going to assume a datasheet erratum here. */
coef = 16;
break;
case 0x03: /*640x200x4*/
def = 0x56;
coef = 8;
break;
case 0x01: /*80 column text*/
def = 0x5a;
coef = 8;
break;
case 0x00: /*40 column text*/
default:
def = 0x2c;
coef = 16;
break;
case 0x02: /*320x200x4*/
def = 0x2b;
coef = 16;
break;
case 0x102: /*640x200x2*/
def = 0x2b;
coef = 16;
break;
}
ret = pcjr->crtc[0x02] - def;
if (ret < -8)
ret = -8;
if (ret > 8)
ret = 8;
return ret * coef;
}
static void
vid_blit_h_overscan(pcjr_t *pcjr)
{
int cols = (pcjr->array[2] & 0xf) + 16;;
int y0 = pcjr->firstline << 1;
int y = (pcjr->lastline << 1) + 16;
int ho_s = vid_get_h_overscan_size(pcjr);
int i;
int x;
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
for (i = 0; i < 16; i++) {
hline(buffer32, 0, y0 + i, x, cols);
hline(buffer32, 0, y + i, x, cols);
if (pcjr->composite) {
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y0 + i]);
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y + i]);
} else {
video_process_8(x, y0 + i);
video_process_8(x, y + i);
}
}
}
static void
vid_poll(void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
uint16_t ca = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int xs_temp;
int ys_temp;
int oldvc;
uint8_t chr;
uint8_t attr;
uint16_t dat;
int cols[4];
int oldsc;
int l = (pcjr->displine << 1) + 16;
int ho_s = vid_get_h_overscan_size(pcjr);
int ho_d = vid_get_h_overscan_delta(pcjr) + (ho_s / 2);
if (!pcjr->linepos) {
timer_advance_u64(&pcjr->timer, pcjr->dispofftime);
pcjr->stat &= ~1;
pcjr->linepos = 1;
oldsc = pcjr->sc;
if ((pcjr->crtc[8] & 3) == 3)
pcjr->sc = (pcjr->sc << 1) & 7;
if (pcjr->dispon) {
uint16_t offset = 0;
uint16_t mask = 0x1fff;
if (pcjr->displine < pcjr->firstline) {
pcjr->firstline = pcjr->displine;
video_wait_for_buffer();
}
pcjr->lastline = pcjr->displine;
cols[0] = (pcjr->array[2] & 0xf) + 16;
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
}
switch (pcjr->addr_mode) {
case 0: /*Alpha*/
offset = 0;
mask = 0x3fff;
break;
case 1: /*Low resolution graphics*/
offset = (pcjr->sc & 1) * 0x2000;
break;
case 3: /*High resolution graphics*/
offset = (pcjr->sc & 3) * 0x2000;
break;
default:
break;
}
switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) {
case 0x13: /*320x200x16*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
pcjr->ma++;
buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] =
buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] =
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] =
buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] =
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] =
buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] =
buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x12: /*160x200x16*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
pcjr->ma++;
buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] =
buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] =
buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] =
buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] =
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] =
buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] =
buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] =
buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] =
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 8] = buffer32->line[l][ef_x + 9] =
buffer32->line[l][ef_x + 10] = buffer32->line[l][ef_x + 11] =
buffer32->line[l + 1][ef_x + 8] = buffer32->line[l + 1][ef_x + 9] =
buffer32->line[l + 1][ef_x + 10] = buffer32->line[l + 1][ef_x + 11] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 12] = buffer32->line[l][ef_x + 13] =
buffer32->line[l][ef_x + 14] = buffer32->line[l][ef_x + 15] =
buffer32->line[l + 1][ef_x + 12] = buffer32->line[l + 1][ef_x + 13] =
buffer32->line[l + 1][ef_x + 14] = buffer32->line[l + 1][ef_x + 15] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x03: /*640x200x4*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset];
pcjr->ma++;
for (uint8_t c = 0; c < 8; c++) {
chr = (dat >> 7) & 1;
chr |= ((dat >> 14) & 2);
buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] =
pcjr->array[(chr & pcjr->array[1] & 0x0f) + 16] + 16;
dat <<= 1;
}
}
break;
case 0x01: /*80 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
if (pcjr->sc & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + c] =
buffer32->line[l + 1][ef_x + c] = cols[0];
else
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + c] =
buffer32->line[l + 1][ef_x + c] =
cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor)
for (uint8_t c = 0; c < 8; c++) {
buffer32->line[l][ef_x + c] ^= 15;
buffer32->line[l + 1][ef_x + c] ^= 15;
}
pcjr->ma++;
}
break;
case 0x00: /*40 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
pcjr->ma++;
if (pcjr->sc & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[0];
else
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] =
cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor)
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[l][ef_x + c] ^= 15;
buffer32->line[l + 1][ef_x + c] ^= 15;
}
}
break;
case 0x02: /*320x200x4*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
cols[2] = pcjr->array[2 + 16] + 16;
cols[3] = pcjr->array[3 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
pcjr->ma++;
for (uint8_t c = 0; c < 8; c++) {
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[dat >> 14];
dat <<= 2;
}
}
break;
case 0x102: /*640x200x2*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1];
pcjr->ma++;
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] =
cols[dat >> 15];
dat <<= 1;
}
}
break;
default:
break;
}
} else {
if (pcjr->array[3] & 4) {
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16);
}
} else {
cols[0] = pcjr->array[0 + 16] + 16;
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
}
}
}
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
if (pcjr->composite) {
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l]);
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l + 1]);
} else {
video_process_8(x, l);
video_process_8(x, l + 1);
}
pcjr->sc = oldsc;
if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) {
pcjr->stat |= 8;
}
pcjr->displine++;
if (pcjr->displine >= 360)
pcjr->displine = 0;
} else {
timer_advance_u64(&pcjr->timer, pcjr->dispontime);
if (pcjr->dispon)
pcjr->stat |= 1;
pcjr->linepos = 0;
if (pcjr->vsynctime) {
pcjr->vsynctime--;
if (!pcjr->vsynctime) {
pcjr->stat &= ~8;
}
}
if (pcjr->sc == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[11] & 31) >> 1))) {
pcjr->con = 0;
pcjr->coff = 1;
}
if (pcjr->vadj) {
pcjr->sc++;
pcjr->sc &= 31;
pcjr->ma = pcjr->maback;
pcjr->vadj--;
if (!pcjr->vadj) {
pcjr->dispon = 1;
pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
pcjr->sc = 0;
}
} else if (pcjr->sc == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == (pcjr->crtc[9] >> 1))) {
pcjr->maback = pcjr->ma;
pcjr->sc = 0;
oldvc = pcjr->vc;
pcjr->vc++;
pcjr->vc &= 127;
if (pcjr->vc == pcjr->crtc[6])
pcjr->dispon = 0;
if (oldvc == pcjr->crtc[4]) {
pcjr->vc = 0;
pcjr->vadj = pcjr->crtc[5];
if (!pcjr->vadj)
pcjr->dispon = 1;
if (!pcjr->vadj)
pcjr->ma = pcjr->maback = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
if ((pcjr->crtc[10] & 0x60) == 0x20)
pcjr->cursoron = 0;
else
pcjr->cursoron = pcjr->blink & 16;
}
if (pcjr->vc == pcjr->crtc[7]) {
pcjr->dispon = 0;
pcjr->displine = 0;
pcjr->vsynctime = 16;
picint(1 << 5);
if (pcjr->crtc[7]) {
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
pcjr->lastline++;
xs_temp = x;
ys_temp = (pcjr->lastline - pcjr->firstline) << 1;
if ((xs_temp > 0) && (ys_temp > 0)) {
int actual_ys = ys_temp;
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= ho_s;
if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 32 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
vid_blit_h_overscan(pcjr);
if (enable_overscan) {
video_blit_memtoscreen(0, pcjr->firstline << 1,
xsize, actual_ys + 32);
} else if (pcjr->apply_hd) {
video_blit_memtoscreen(ho_s / 2, (pcjr->firstline << 1) + 16,
xsize, actual_ys);
} else {
video_blit_memtoscreen(ho_d, (pcjr->firstline << 1) + 16,
xsize, actual_ys);
}
}
frames++;
video_res_x = xsize;
video_res_y = ysize;
}
pcjr->firstline = 1000;
pcjr->lastline = 0;
pcjr->blink++;
}
} else {
pcjr->sc++;
pcjr->sc &= 31;
pcjr->ma = pcjr->maback;
}
if (pcjr->sc == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->sc == ((pcjr->crtc[10] & 31) >> 1)))
pcjr->con = 1;
}
}
static void
kbd_write(uint16_t port, uint8_t val, void *priv)
@@ -1435,35 +756,7 @@ speed_changed(void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
recalc_timings(pcjr);
}
static void
pcjr_vid_init(pcjr_t *pcjr)
{
int display_type;
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram);
pcjr->memctrl = -1;
if (mem_size < 128)
pcjr->memctrl &= ~0x24;
display_type = device_get_config_int("display_type");
pcjr->composite = (display_type != PCJR_RGB);
pcjr->apply_hd = device_get_config_int("apply_hd");
overscan_x = 256;
overscan_y = 32;
mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000,
vid_read, NULL, NULL,
vid_write, NULL, NULL, NULL, 0, pcjr);
io_sethandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr);
timer_add(&pcjr->timer, vid_poll, pcjr, 1);
cga_palette = 0;
cgapal_rebuild();
pcjr_recalc_timings(pcjr);
}
void

View File

@@ -44,12 +44,9 @@
#include <86box/video.h>
#include <86box/vid_cga_comp.h>
#include <86box/machine.h>
#include <86box/m_tandy.h>
#include <86box/plat_unused.h>
enum {
TANDY_RGB = 0,
TANDY_COMPOSITE
};
enum {
TYPE_TANDY = 0,
@@ -65,80 +62,6 @@ enum {
EEPROM_WRITE
};
typedef struct t1kvid_t {
mem_mapping_t mapping;
mem_mapping_t vram_mapping;
uint8_t crtc[32];
int crtcreg;
int array_index;
uint8_t array[256];
int memctrl;
uint8_t mode;
uint8_t col;
uint8_t stat;
uint8_t *vram;
uint8_t *b8000;
uint32_t b8000_mask;
uint32_t b8000_limit;
uint8_t planar_ctrl;
uint8_t lp_strobe;
int linepos;
int displine;
int sc;
int vc;
int dispon;
int con;
int coff;
int cursoron;
int blink;
int fullchange;
int vsynctime;
int vadj;
uint16_t ma;
uint16_t maback;
uint64_t dispontime;
uint64_t dispofftime;
pc_timer_t timer;
int firstline;
int lastline;
int composite;
} t1kvid_t;
typedef struct t1keep_t {
char *path;
int state;
int count;
int addr;
int clk;
uint16_t data;
uint16_t store[64];
} t1keep_t;
typedef struct tandy_t {
mem_mapping_t ram_mapping;
mem_mapping_t rom_mapping; /* SL2 */
uint8_t *rom; /* SL2 */
uint8_t ram_bank;
uint8_t rom_bank; /* SL2 */
int rom_offset; /* SL2 */
uint32_t base;
uint32_t mask;
int is_hx;
int is_sl2;
t1kvid_t *vid;
} tandy_t;
static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/
static const scancode scancode_tandy[512] = {
// clang-format off
@@ -656,22 +579,8 @@ static const scancode scancode_tandy[512] = {
{ .mk = { 0 }, .brk = { 0 } } /* 1ff */
// clang-format on
};
static uint8_t crtcmask[32] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f,
0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static uint8_t crtcmask_sl[32] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff,
0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static int eep_data_out;
static uint8_t vid_in(uint16_t addr, void *priv);
static void vid_out(uint16_t addr, uint8_t val, void *priv);
static int eep_data_out;
#ifdef ENABLE_TANDY_LOG
int tandy_do_log = ENABLE_TANDY_LOG;
@@ -691,763 +600,7 @@ tandy_log(const char *fmt, ...)
# define tandy_log(fmt, ...)
#endif
static void
recalc_mapping(tandy_t *dev)
{
t1kvid_t *vid = dev->vid;
mem_mapping_disable(&vid->mapping);
io_removehandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
if (vid->planar_ctrl & 4) {
mem_mapping_enable(&vid->mapping);
if (vid->array[5] & 1)
mem_mapping_set_addr(&vid->mapping, 0xa0000, 0x10000);
else
mem_mapping_set_addr(&vid->mapping, 0xb8000, 0x8000);
io_sethandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
}
}
static void
recalc_timings(tandy_t *dev)
{
t1kvid_t *vid = dev->vid;
double _dispontime;
double _dispofftime;
double disptime;
if (vid->mode & 1) {
disptime = vid->crtc[0] + 1;
_dispontime = vid->crtc[1];
} else {
disptime = (vid->crtc[0] + 1) << 1;
_dispontime = vid->crtc[1] << 1;
}
_dispofftime = disptime - _dispontime;
_dispontime *= CGACONST;
_dispofftime *= CGACONST;
vid->dispontime = (uint64_t) (_dispontime);
vid->dispofftime = (uint64_t) (_dispofftime);
}
static void
recalc_address(tandy_t *dev)
{
t1kvid_t *vid = dev->vid;
if ((vid->memctrl & 0xc0) == 0xc0) {
vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base];
vid->b8000_mask = 0x7fff;
} else {
vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base];
vid->b8000_mask = 0x3fff;
}
}
static void
recalc_address_sl(tandy_t *dev)
{
t1kvid_t *vid = dev->vid;
vid->b8000_limit = 0x8000;
if (vid->array[5] & 1) {
vid->vram = &ram[((vid->memctrl & 0x04) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x20) << 11) + dev->base];
} else if ((vid->memctrl & 0xc0) == 0xc0) {
vid->vram = &ram[((vid->memctrl & 0x06) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x30) << 11) + dev->base];
} else {
vid->vram = &ram[((vid->memctrl & 0x07) << 14) + dev->base];
vid->b8000 = &ram[((vid->memctrl & 0x38) << 11) + dev->base];
if ((vid->memctrl & 0x38) == 0x38)
vid->b8000_limit = 0x4000;
}
}
static void
vid_update_latch(t1kvid_t *vid)
{
uint32_t lp_latch = vid->displine * vid->crtc[1];
vid->crtc[0x10] = (lp_latch >> 8) & 0x3f;
vid->crtc[0x11] = lp_latch & 0xff;
}
static void
vid_out(uint16_t addr, uint8_t val, void *priv)
{
tandy_t *dev = (tandy_t *) priv;
t1kvid_t *vid = dev->vid;
uint8_t old;
if ((addr >= 0x3d0) && (addr <= 0x3d7))
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x03d4:
vid->crtcreg = val & 0x1f;
break;
case 0x03d5:
old = vid->crtc[vid->crtcreg];
if (dev->is_sl2)
vid->crtc[vid->crtcreg] = val & crtcmask_sl[vid->crtcreg];
else
vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg];
if (old != val) {
if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) {
vid->fullchange = changeframecount;
recalc_timings(dev);
}
}
break;
case 0x03d8:
old = vid->mode;
vid->mode = val;
if ((old ^ val) & 0x01)
recalc_timings(dev);
if (!dev->is_sl2)
update_cga16_color(vid->mode);
break;
case 0x03d9:
vid->col = val;
break;
case 0x03da:
vid->array_index = val & 0x1f;
break;
case 0x3db:
if (!dev->is_sl2 && (vid->lp_strobe == 1))
vid->lp_strobe = 0;
break;
case 0x3dc:
if (!dev->is_sl2 && (vid->lp_strobe == 0)) {
vid->lp_strobe = 1;
vid_update_latch(vid);
}
break;
case 0x03de:
if (vid->array_index & 16)
val &= 0xf;
vid->array[vid->array_index & 0x1f] = val;
if (dev->is_sl2) {
if ((vid->array_index & 0x1f) == 5) {
recalc_mapping(dev);
recalc_address_sl(dev);
}
}
break;
case 0x03df:
vid->memctrl = val;
if (dev->is_sl2)
recalc_address_sl(dev);
else
recalc_address(dev);
break;
case 0x0065:
if (val == 8)
return; /*Hack*/
vid->planar_ctrl = val;
recalc_mapping(dev);
break;
default:
break;
}
}
static uint8_t
vid_in(uint16_t addr, void *priv)
{
const tandy_t *dev = (tandy_t *) priv;
t1kvid_t *vid = dev->vid;
uint8_t ret = 0xff;
if ((addr >= 0x3d0) && (addr <= 0x3d7))
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x03d4:
ret = vid->crtcreg;
break;
case 0x03d5:
ret = vid->crtc[vid->crtcreg];
break;
case 0x03da:
ret = vid->stat;
break;
case 0x3db:
if (!dev->is_sl2 && (vid->lp_strobe == 1))
vid->lp_strobe = 0;
break;
case 0x3dc:
if (!dev->is_sl2 && (vid->lp_strobe == 0)) {
vid->lp_strobe = 1;
vid_update_latch(vid);
}
break;
default:
break;
}
return ret;
}
static void
vid_write(uint32_t addr, uint8_t val, void *priv)
{
tandy_t *dev = (tandy_t *) priv;
t1kvid_t *vid = dev->vid;
if (vid->memctrl == -1)
return;
if (dev->is_sl2) {
if (vid->array[5] & 1)
vid->b8000[addr & 0xffff] = val;
else {
if ((addr & 0x7fff) < vid->b8000_limit)
vid->b8000[addr & 0x7fff] = val;
}
} else {
vid->b8000[addr & vid->b8000_mask] = val;
}
}
static uint8_t
vid_read(uint32_t addr, void *priv)
{
const tandy_t *dev = (tandy_t *) priv;
const t1kvid_t *vid = dev->vid;
if (vid->memctrl == -1)
return 0xff;
if (dev->is_sl2) {
if (vid->array[5] & 1)
return (vid->b8000[addr & 0xffff]);
if ((addr & 0x7fff) < vid->b8000_limit)
return (vid->b8000[addr & 0x7fff]);
else
return 0xff;
} else {
return (vid->b8000[addr & vid->b8000_mask]);
}
}
static void
vid_poll(void *priv)
{
tandy_t *dev = (tandy_t *) priv;
t1kvid_t *vid = dev->vid;
uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
int xs_temp;
int ys_temp;
int oldvc;
uint8_t chr;
uint8_t attr;
uint16_t dat;
int cols[4];
int col;
int oldsc;
if (!vid->linepos) {
timer_advance_u64(&vid->timer, vid->dispofftime);
vid->stat |= 1;
vid->linepos = 1;
oldsc = vid->sc;
if ((vid->crtc[8] & 3) == 3)
vid->sc = (vid->sc << 1) & 7;
if (vid->dispon) {
if (vid->displine < vid->firstline) {
vid->firstline = vid->displine;
video_wait_for_buffer();
}
vid->lastline = vid->displine;
cols[0] = (vid->array[2] & 0xf) + 16;
for (c = 0; c < 8; c++) {
if (vid->array[3] & 4) {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = cols[0];
if (vid->mode & 1) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = cols[0];
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = cols[0];
}
} else if ((vid->mode & 0x12) == 0x12) {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = 0;
if (vid->mode & 1) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = 0;
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = 0;
}
} else {
buffer32->line[vid->displine << 1][c] = buffer32->line[(vid->displine << 1) + 1][c] = (vid->col & 15) + 16;
if (vid->mode & 1) {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 3) + 8] = (vid->col & 15) + 16;
} else {
buffer32->line[vid->displine << 1][c + (vid->crtc[1] << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][c + (vid->crtc[1] << 4) + 8] = (vid->col & 15) + 16;
}
}
}
if (dev->is_sl2 && (vid->array[5] & 1)) { /*640x200x16*/
for (x = 0; x < vid->crtc[1] * 2; x++) {
dat = (vid->vram[(vid->ma << 1) & 0xffff] << 8) | vid->vram[((vid->ma << 1) + 1) & 0xffff];
vid->ma++;
buffer32->line[vid->displine << 1][(x << 2) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 8] = vid->array[((dat >> 12) & 0xf) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 2) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 9] = vid->array[((dat >> 8) & 0xf) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 2) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 10] = vid->array[((dat >> 4) & 0xf) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 2) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 2) + 11] = vid->array[(dat & 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->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1];
vid->ma++;
buffer32->line[vid->displine << 1][(x << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8] = buffer32->line[vid->displine << 1][(x << 3) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 3) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 10] = buffer32->line[vid->displine << 1][(x << 3) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 3) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 12] = buffer32->line[vid->displine << 1][(x << 3) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 3) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 14] = buffer32->line[vid->displine << 1][(x << 3) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 15] = vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16;
}
} else if (vid->array[3] & 0x10) { /*160x200x16*/
for (x = 0; x < vid->crtc[1]; x++) {
if (dev->is_sl2) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1];
} else {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1];
}
vid->ma++;
buffer32->line[vid->displine << 1][(x << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 8] = buffer32->line[vid->displine << 1][(x << 4) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 9] = buffer32->line[vid->displine << 1][(x << 4) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 10] = buffer32->line[vid->displine << 1][(x << 4) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 4) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 12] = buffer32->line[vid->displine << 1][(x << 4) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 13] = buffer32->line[vid->displine << 1][(x << 4) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 14] = buffer32->line[vid->displine << 1][(x << 4) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 4) + 16] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 16] = buffer32->line[vid->displine << 1][(x << 4) + 17] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 17] = buffer32->line[vid->displine << 1][(x << 4) + 18] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 18] = buffer32->line[vid->displine << 1][(x << 4) + 19] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16;
buffer32->line[vid->displine << 1][(x << 4) + 20] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 20] = buffer32->line[vid->displine << 1][(x << 4) + 21] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 21] = buffer32->line[vid->displine << 1][(x << 4) + 22] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 22] = buffer32->line[vid->displine << 1][(x << 4) + 23] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 23] = vid->array[(dat & 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->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1];
vid->ma++;
for (c = 0; c < 8; c++) {
chr = (dat >> 6) & 2;
chr |= ((dat >> 15) & 1);
buffer32->line[vid->displine << 1][(x << 3) + 8 + c] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8 + c] = vid->array[(chr & vid->array[1]) + 16] + 16;
dat <<= 1;
}
}
} else if (vid->mode & 1) {
for (x = 0; x < vid->crtc[1]; x++) {
chr = vid->vram[(vid->ma << 1) & 0x3fff];
attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->mode & 0x20) {
cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16;
cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16;
if ((vid->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16;
cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16;
}
if (vid->sc & 8) {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[0];
}
} else {
for (c = 0; c < 8; c++) {
if (vid->sc == 8) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0];
} else {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 3) + c + 8] ^= 15;
buffer32->line[(vid->displine << 1) + 1][(x << 3) + c + 8] ^= 15;
}
}
vid->ma++;
}
} else if (!(vid->mode & 2)) {
for (x = 0; x < vid->crtc[1]; x++) {
chr = vid->vram[(vid->ma << 1) & 0x3fff];
attr = vid->vram[((vid->ma << 1) + 1) & 0x3fff];
drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron);
if (vid->mode & 0x20) {
cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16;
cols[0] = vid->array[(((attr >> 4) & 7) & vid->array[1]) + 16] + 16;
if ((vid->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = vid->array[((attr & 15) & vid->array[1]) + 16] + 16;
cols[0] = vid->array[((attr >> 4) & vid->array[1]) + 16] + 16;
}
vid->ma++;
if (vid->sc & 8) {
for (c = 0; c < 8; c++)
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = cols[0];
} else {
for (c = 0; c < 8; c++) {
if (vid->sc == 8) {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][7] & (1 << (c ^ 7))) ? 1 : 0];
} else {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
if (drawcursor) {
for (c = 0; c < 16; c++) {
buffer32->line[vid->displine << 1][(x << 4) + c + 8] ^= 15;
buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] ^= 15;
}
}
}
} else if (!(vid->mode & 16)) {
cols[0] = (vid->col & 15);
col = (vid->col & 16) ? 8 : 0;
if (vid->mode & 4) {
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
} else if (vid->col & 32) {
cols[1] = col | 3;
cols[2] = col | 5;
cols[3] = col | 7;
} else {
cols[1] = col | 2;
cols[2] = col | 4;
cols[3] = col | 6;
}
cols[0] = vid->array[(cols[0] & vid->array[1]) + 16] + 16;
cols[1] = vid->array[(cols[1] & vid->array[1]) + 16] + 16;
cols[2] = vid->array[(cols[2] & vid->array[1]) + 16] + 16;
cols[3] = vid->array[(cols[3] & vid->array[1]) + 16] + 16;
for (x = 0; x < vid->crtc[1]; x++) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1];
vid->ma++;
for (c = 0; c < 8; c++) {
buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[vid->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14];
dat <<= 2;
}
}
} else {
cols[0] = 0;
cols[1] = vid->array[(vid->col & vid->array[1]) + 16] + 16;
for (x = 0; x < vid->crtc[1]; x++) {
dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1];
vid->ma++;
for (c = 0; c < 16; c++) {
buffer32->line[vid->displine << 1][(x << 4) + c + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15];
dat <<= 1;
}
}
}
} else {
if (vid->array[3] & 4) {
if (vid->mode & 1) {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16);
} else {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16);
}
} else {
cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16;
if (vid->mode & 1) {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 3) + 16, cols[0]);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 3) + 16, cols[0]);
} else {
hline(buffer32, 0, (vid->displine << 1), (vid->crtc[1] << 4) + 16, cols[0]);
hline(buffer32, 0, (vid->displine << 1) + 1, (vid->crtc[1] << 4) + 16, cols[0]);
}
}
}
if (vid->mode & 1)
x = (vid->crtc[1] << 3) + 16;
else
x = (vid->crtc[1] << 4) + 16;
if (!dev->is_sl2 && vid->composite) {
Composite_Process(vid->mode, 0, x >> 2, buffer32->line[vid->displine << 1]);
Composite_Process(vid->mode, 0, x >> 2, buffer32->line[(vid->displine << 1) + 1]);
} else {
video_process_8(x, vid->displine << 1);
video_process_8(x, (vid->displine << 1) + 1);
}
vid->sc = oldsc;
if (vid->vc == vid->crtc[7] && !vid->sc)
vid->stat |= 8;
vid->displine++;
if (vid->displine >= 360)
vid->displine = 0;
} else {
timer_advance_u64(&vid->timer, vid->dispontime);
if (vid->dispon)
vid->stat &= ~1;
vid->linepos = 0;
if (vid->vsynctime) {
vid->vsynctime--;
if (!vid->vsynctime)
vid->stat &= ~8;
}
if (vid->sc == (vid->crtc[11] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[11] & 31) >> 1))) {
vid->con = 0;
vid->coff = 1;
}
if (vid->vadj) {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
vid->vadj--;
if (!vid->vadj) {
vid->dispon = 1;
if (dev->is_sl2 && (vid->array[5] & 1))
vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8);
else
vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff;
vid->sc = 0;
}
} else if (vid->sc == vid->crtc[9] || ((vid->crtc[8] & 3) == 3 && vid->sc == (vid->crtc[9] >> 1))) {
vid->maback = vid->ma;
vid->sc = 0;
oldvc = vid->vc;
vid->vc++;
if (dev->is_sl2)
vid->vc &= 255;
else
vid->vc &= 127;
if (vid->vc == vid->crtc[6])
vid->dispon = 0;
if (oldvc == vid->crtc[4]) {
vid->vc = 0;
vid->vadj = vid->crtc[5];
if (!vid->vadj)
vid->dispon = 1;
if (!vid->vadj) {
if (dev->is_sl2 && (vid->array[5] & 1))
vid->ma = vid->maback = vid->crtc[13] | (vid->crtc[12] << 8);
else
vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff;
}
if ((vid->crtc[10] & 0x60) == 0x20)
vid->cursoron = 0;
else
vid->cursoron = vid->blink & 16;
}
if (vid->vc == vid->crtc[7]) {
vid->dispon = 0;
vid->displine = 0;
vid->vsynctime = 16;
picint(1 << 5);
if (vid->crtc[7]) {
if (vid->mode & 1)
x = (vid->crtc[1] << 3) + 16;
else
x = (vid->crtc[1] << 4) + 16;
vid->lastline++;
xs_temp = x;
ys_temp = (vid->lastline - vid->firstline) << 1;
if ((xs_temp > 0) && (ys_temp > 0)) {
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= 16;
if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
if (enable_overscan) {
video_blit_memtoscreen(0, (vid->firstline - 4) << 1,
xsize, ((vid->lastline - vid->firstline) + 8) << 1);
} else {
video_blit_memtoscreen(8, vid->firstline << 1,
xsize, (vid->lastline - vid->firstline) << 1);
}
}
frames++;
video_res_x = xsize;
video_res_y = ysize;
if ((vid->array[3] & 0x10) && (vid->mode & 1)) { /*320x200x16*/
video_res_x /= 2;
video_bpp = 4;
} else if (vid->array[3] & 0x10) { /*160x200x16*/
video_res_x /= 4;
video_bpp = 4;
} else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/
video_bpp = 2;
} else if (vid->mode & 1) {
video_res_x /= 8;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (!(vid->mode & 2)) {
video_res_x /= 16;
video_res_y /= vid->crtc[9] + 1;
video_bpp = 0;
} else if (!(vid->mode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else {
video_bpp = 1;
}
}
vid->firstline = 1000;
vid->lastline = 0;
vid->blink++;
}
} else {
vid->sc++;
vid->sc &= 31;
vid->ma = vid->maback;
}
if (vid->sc == (vid->crtc[10] & 31) || ((vid->crtc[8] & 3) == 3 && vid->sc == ((vid->crtc[10] & 31) >> 1)))
vid->con = 1;
}
}
static void
vid_speed_changed(void *priv)
{
tandy_t *dev = (tandy_t *) priv;
recalc_timings(dev);
}
static void
vid_close(void *priv)
{
tandy_t *dev = (tandy_t *) priv;
free(dev->vid);
dev->vid = NULL;
}
static void
vid_init(tandy_t *dev)
{
int display_type;
t1kvid_t *vid;
vid = calloc(1, sizeof(t1kvid_t));
vid->memctrl = -1;
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram);
display_type = device_get_config_int("display_type");
vid->composite = (display_type != TANDY_RGB);
cga_comp_init(1);
if (dev->is_sl2) {
vid->b8000_limit = 0x8000;
vid->planar_ctrl = 4;
overscan_x = overscan_y = 16;
io_sethandler(0x0065, 1, vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
} else
vid->b8000_mask = 0x3fff;
timer_add(&vid->timer, vid_poll, dev, 1);
mem_mapping_add(&vid->mapping, 0xb8000, 0x08000,
vid_read, NULL, NULL, vid_write, NULL, NULL, NULL, 0, dev);
io_sethandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
dev->vid = vid;
}
const device_config_t vid_config[] = {
// clang-format off
{
.name = "display_type",
.description = "Display type",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = TANDY_RGB,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "RGB", .value = TANDY_RGB },
{ .description = "Composite", .value = TANDY_COMPOSITE },
{ .description = "" }
}
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t vid_device = {
.name = "Tandy 1000",
.internal_name = "tandy1000_video",
.flags = 0,
.local = 0,
.init = NULL,
.close = vid_close,
.reset = NULL,
.available = NULL,
.speed_changed = vid_speed_changed,
.force_redraw = NULL,
.config = vid_config
};
const device_t vid_device_hx = {
.name = "Tandy 1000 HX",
.internal_name = "tandy1000_hx_video",
.flags = 0,
.local = 0,
.init = NULL,
.close = vid_close,
.reset = NULL,
.available = NULL,
.speed_changed = vid_speed_changed,
.force_redraw = NULL,
.config = vid_config
};
const device_t vid_device_sl = {
.name = "Tandy 1000SL2",
.internal_name = "tandy1000_sl_video",
.flags = 0,
.local = 1,
.init = NULL,
.close = vid_close,
.reset = NULL,
.available = NULL,
.speed_changed = vid_speed_changed,
.force_redraw = NULL,
.config = NULL
};
static void
eep_write(UNUSED(uint16_t addr), uint8_t val, void *priv)
@@ -1632,12 +785,12 @@ tandy_write(uint16_t addr, uint8_t val, void *priv)
}
if (dev->is_hx) {
io_removehandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev);
if (val & 0x01)
mem_mapping_disable(&dev->vid->mapping);
else {
io_sethandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, dev);
tandy_vid_in, NULL, NULL, tandy_vid_out, NULL, NULL, dev);
mem_mapping_set_addr(&dev->vid->mapping, 0xb8000, 0x8000);
}
} else {
@@ -1656,7 +809,7 @@ tandy_write(uint16_t addr, uint8_t val, void *priv)
mem_mapping_set_addr(&dev->ram_mapping,
((val >> 1) & 7) * 128 * 1024,
0x20000);
recalc_address_sl(dev);
tandy_recalc_address_sl(dev);
dev->ram_bank = val;
break;
@@ -1805,10 +958,10 @@ machine_tandy1k_init(const machine_t *model, int type)
keyboard_set_table(scancode_tandy);
io_sethandler(0x00a0, 1,
tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev);
device_context(&vid_device);
vid_init(dev);
device_context(&tandy_1000_video_device);
tandy_vid_init(dev);
device_context_restore();
device_add_ex(&vid_device, dev);
device_add_ex(&tandy_1000_video_device, dev);
device_add((type == TYPE_TANDY1000SX) ? &ncr8496_device : &sn76489_device);
break;
@@ -1817,10 +970,10 @@ machine_tandy1k_init(const machine_t *model, int type)
keyboard_set_table(scancode_tandy);
io_sethandler(0x00a0, 1,
tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev);
device_context(&vid_device_hx);
vid_init(dev);
device_context(&tandy_1000hx_video_device);
tandy_vid_init(dev);
device_context_restore();
device_add_ex(&vid_device_hx, dev);
device_add_ex(&tandy_1000hx_video_device, dev);
device_add(&ncr8496_device);
device_add(&eep_1000hx_device);
break;
@@ -1830,10 +983,10 @@ machine_tandy1k_init(const machine_t *model, int type)
init_rom(dev);
io_sethandler(0xffe8, 8,
tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev);
device_context(&vid_device_sl);
vid_init(dev);
device_context(&tandy_1000sl_video_device);
tandy_vid_init(dev);
device_context_restore();
device_add_ex(&vid_device_sl, dev);
device_add_ex(&tandy_1000sl_video_device, dev);
device_add(&pssj_device);
device_add(&eep_1000sl2_device);
break;

View File

@@ -85,7 +85,7 @@ static const device_config_t ibmpc_config[] = {
{ .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } },
{ .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } },
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.4_8kb.bin", "" } },
{ .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } },
{ .files_no = 0 }
@@ -195,7 +195,7 @@ static const device_config_t ibmpc82_config[] = {
{ .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } },
{ .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } },
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.4_8kb.bin", "" } },
{ .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } },
{ .files_no = 0 }
@@ -282,48 +282,103 @@ machine_pc82_init(const machine_t *model)
static const device_config_t ibmxt_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "ibm5160_1501512_5000027",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "1501512 (11/08/82)", .internal_name = "ibm5160_1501512_5000027", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" } },
{ .name = "1501512 (11/08/82) (Alt)", .internal_name = "ibm5160_1501512_6359116", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" } },
{ .name = "5000026 (08/16/82)", .internal_name = "ibm5160_5000026_5000027", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" } },
#if 0
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.bios = {
{
.name = "1501512 (11/08/82)",
.internal_name = "ibm5160_1501512_5000027",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" }
},
{
.name = "1501512 (11/08/82) (Alt)",
.internal_name = "ibm5160_1501512_6359116",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmxt/BIOS_5160_08NOV82_U18_1501512.BIN", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_6359116.BIN", "" }
},
{
.name = "5000026 (08/16/82)",
.internal_name = "ibm5160_5000026_5000027",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmxt/BIOS_5160_16AUG82_U18_5000026.BIN", "roms/machines/ibmxt/BIOS_5160_16AUG82_U19_5000027.BIN", "" }
},
// GlaBIOS for IBM XT
{ .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "" } },
{ .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "" } },
{
.name = "GlaBIOS 0.2.5 (8088)",
.internal_name = "glabios_025_8088",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 1,
.size = 40960,
.files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" }
},
{
.name = "GlaBIOS 0.2.5 (V20)",
.internal_name = "glabios_025_v20",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 1,
.size = 40960,
.files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" }
},
// The following are Diagnostic ROMs.
{ .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } },
{ .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } },
{ .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } },
#endif
{
.name = "Supersoft Diagnostics",
.internal_name = "diag_supersoft",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 2,
.size = 65536,
.files = { "roms/machines/diagnostic/Supersoft_PCXT_32KB.bin", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" }
},
{
.name = "Ruud's Diagnostic Rom",
.internal_name = "diag_ruuds",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 2,
.size = 65536,
.files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.4_32kb.bin", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" }
},
{
.name = "XT RAM Test",
.internal_name = "diag_xtramtest",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 2,
.size = 65536,
.files = { "roms/machines/diagnostic/xtramtest_32k.bin", "roms/machines/ibmxt/BIOS_5160_08NOV82_U19_5000027.BIN", "" }
},
{ .files_no = 0 }
},
},
{
.name = "enable_5161",
.name = "enable_5161",
.description = "IBM 5161 Expansion Unit",
.type = CONFIG_BINARY,
.type = CONFIG_BINARY,
.default_int = 1
},
{
.name = "enable_basic",
.name = "enable_basic",
.description = "IBM Cassette Basic",
.type = CONFIG_BINARY,
.type = CONFIG_BINARY,
.default_int = 1
},
{ .name = "", .description = "", .type = CONFIG_END }
@@ -351,6 +406,8 @@ machine_xt_init(const machine_t *model)
uint8_t enable_5161;
uint8_t enable_basic;
const char *fn;
uint16_t offset = 0;
uint32_t local = 0;
/* No ROMs available. */
if (!device_available(model->device))
@@ -360,11 +417,17 @@ machine_xt_init(const machine_t *model)
enable_5161 = machine_get_config_int("enable_5161");
enable_basic = machine_get_config_int("enable_basic");
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000);
local = device_get_bios_local(model->device, device_get_config_bios("bios"));
if (local == 0) // Offset for stock roms
offset = 0x6000;
ret = bios_load_linear(fn, 0x000fe000, 65536, offset);
if (enable_basic && ret) {
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
(void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0);
if (local == 0) { // needed for stock roms
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
(void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0);
}
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1);
/* On the real machine, the BASIC is repeated. */
(void) bios_load_aux_linear(fn, 0x000f0000, 8192, 0);
@@ -408,42 +471,98 @@ machine_genxt_init(const machine_t *model)
static const device_config_t ibmxt86_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "ibm5160_050986",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "1501512 (05/09/86)", .internal_name = "ibm5160_050986", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" } },
{ .name = "5000026 (01/10/86)", .internal_name = "ibm5160_011086", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0851_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0854_27256_F000.BIN", "" } },
{ .name = "1501512 (01/10/86) (Alt)", .internal_name = "ibm5160_011086_alt", .bios_type = BIOS_NORMAL,
.files_no = 2, .local = 0, .size = 65536, .files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0852_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0853_27256_F000.BIN", "" } },
#if 0
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.bios = {
{
.name = "1501512 (05/09/86)",
.internal_name = "ibm5160_050986",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" }
},
{
.name = "5000026 (01/10/86)",
.internal_name = "ibm5160_011086",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0851_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0854_27256_F000.BIN", "" }
},
{
.name = "1501512 (01/10/86) (Alt)",
.internal_name = "ibm5160_011086_alt",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 0,
.size = 65536,
.files = { "roms/machines/ibmxt86/BIOS_5160_10JAN86_U18_62X0852_27256_F800.BIN", "roms/machines/ibmxt86/BIOS_5160_10JAN86_U19_62X0853_27256_F000.BIN", "" }
},
// GlaBIOS for IBM XT
{ .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "" } },
{ .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 40960, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "" } },
{
.name = "GlaBIOS 0.2.5 (8088)",
.internal_name = "glabios_025_8088",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 1,
.size = 65536,
.files = { "roms/machines/glabios/GLABIOS_0.2.5_8X.ROM", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" }
},
{
.name = "GlaBIOS 0.2.5 (V20)",
.internal_name = "glabios_025_v20",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 1,
.size = 65536,
.files = { "roms/machines/glabios/GLABIOS_0.2.5_VX.ROM", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" }
},
// The following are Diagnostic ROMs.
{ .name = "Supersoft Diagnostics", .internal_name = "diag_supersoft", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/Supersoft_PCXT_8KB.bin", "" } },
{ .name = "Ruud's Diagnostic Rom", .internal_name = "diag_ruuds", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.3_8kb.bin", "" } },
{ .name = "XT RAM Test", .internal_name = "diag_xtramtest", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 65536, .files = { "roms/machines/diagnostic/xtramtest_8k.bin", "" } },
#endif
{
.name = "Supersoft Diagnostics",
.internal_name = "diag_supersoft",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 2,
.size = 65536,
.files = { "roms/machines/diagnostic/Supersoft_PCXT_32KB.bin", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" }
},
{
.name = "Ruud's Diagnostic Rom",
.internal_name = "diag_ruuds",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 2,
.size = 65536,
.files = { "roms/machines/diagnostic/ruuds_diagnostic_rom_v5.4_32kb.bin", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" }
},
{
.name = "XT RAM Test",
.internal_name = "diag_xtramtest",
.bios_type = BIOS_NORMAL,
.files_no = 2,
.local = 2,
.size = 65536,
.files = { "roms/machines/diagnostic/xtramtest_32k.bin", "roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", "" }
},
{ .files_no = 0 }
},
},
{
.name = "enable_5161",
.name = "enable_5161",
.description = "IBM 5161 Expansion Unit",
.type = CONFIG_BINARY,
.type = CONFIG_BINARY,
.default_int = 1
},
{ .name = "", .description = "", .type = CONFIG_END }
@@ -470,6 +589,8 @@ machine_xt86_init(const machine_t *model)
int ret = 0;
uint8_t enable_5161;
const char *fn;
uint16_t offset = 0;
uint32_t local = 0;
/* No ROMs available. */
if (!device_available(model->device))
@@ -478,11 +599,17 @@ machine_xt86_init(const machine_t *model)
device_context(model->device);
enable_5161 = machine_get_config_int("enable_5161");
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000fe000, 65536, 0x6000);
local = device_get_bios_local(model->device, device_get_config_bios("bios"));
if (local == 0) // Offset for stock roms
offset = 0x6000;
ret = bios_load_linear(fn, 0x000fe000, 65536, offset);
if (ret) {
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
(void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0);
if (local == 0) { // needed for stock roms
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
(void) bios_load_aux_linear(fn, 0x000f8000, 24576, 0);
}
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 1);
(void) bios_load_aux_linear(fn, 0x000f0000, 32768, 0);
}

View File

@@ -1918,7 +1918,7 @@ m19_vid_out(uint16_t addr, uint8_t val, void *priv)
/* activating plantronics mode */
if (addr == 0x3dd) {
/* already in graphics mode */
if ((val & 0x30) && (vid->ogc.cga.cgamode & 0x2))
if ((val & 0x30) && (vid->ogc.cga.cgamode & CGA_MODE_FLAG_GRAPHICS))
vid->mode = PLANTRONICS_MODE;
else
vid->mode = OLIVETTI_OGC_MODE;

View File

@@ -39,8 +39,10 @@
// Temporarily here till we move everything out into the right files
extern const device_t pcjr_device;
extern const device_t m19_vid_device;
extern const device_t vid_device;
extern const device_t vid_device_hx;
extern const device_t tandy_1000_video_device;
extern const device_t tandy_1000hx_video_device;
extern const device_t tandy_1000sl_video_device;
extern const device_t t1000_video_device;
extern const device_t xi8088_device;
extern const device_t cga_device;
@@ -50,7 +52,6 @@ extern const device_t vid_pc2086_device;
extern const device_t vid_pc3086_device;
extern const device_t vid_200_device;
extern const device_t vid_ppc512_device;
extern const device_t vid_device_sl;
extern const device_t t1200_video_device;
extern const device_t compaq_plasma_device;
extern const device_t ps1_2011_device;
@@ -69,6 +70,7 @@ extern const device_t ap5s_device;
extern const device_t d842_device;
extern const device_t d943_device;
extern const device_t dells333sl_device;
extern const device_t hot433a_device;
const machine_filter_t machine_types[] = {
{ "None", MACHINE_TYPE_NONE },
@@ -1590,7 +1592,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &vid_device,
.vid_device = &tandy_1000_video_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -1629,7 +1631,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &vid_device_hx,
.vid_device = &tandy_1000hx_video_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -2530,7 +2532,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = &vid_device_sl,
.vid_device = &tandy_1000sl_video_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -3415,6 +3417,47 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* No proper pictures of the KBC exist, though it seems to have the IBM AT KBC
firmware. */
{
.name = "[C&T PC/AT] Tulip AT Compact",
.internal_name = "tuliptc7",
.type = MACHINE_TYPE_286,
.chipset = MACHINE_CHIPSET_CT_AT,
.init = machine_at_tuliptc7_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_286,
.block = CPU_BLOCK_NONE,
.min_bus = 6000000,
.max_bus = 12000000,
.min_voltage = 0,
.max_voltage = 0,
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_AT,
.flags = MACHINE_FLAGS_NONE,
.ram = {
.min = 640,
.max = 16384,
.step = 128
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* Has Quadtel KBC firmware. */
{
.name = "[GC103] Quadtel 286 clone",
@@ -3650,7 +3693,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.vid_device = &paradise_pvga1a_ncr3302_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -6605,6 +6648,46 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */
{
.name = "[VLSI 82C486] Tulip 486 DC/DT",
.internal_name = "tuliptc38",
.type = MACHINE_TYPE_486,
.chipset = MACHINE_CHIPSET_VLSI_VL82C486,
.init = machine_at_tuliptc38_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = 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_AT,
.flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM,
.ram = {
.min = 2048,
.max = 32768,
.step = 2048
},
.nvrmask = 127,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/
.vid_device = &gd5426_onboard_device,
.snd_device = NULL,
.net_device = NULL
},
/* Has IBM PS/2 Type 1 KBC firmware. */
{
.name = "[MCA] IBM PS/2 model 70 (type 4)",
@@ -9036,6 +9119,47 @@ const machine_t machines[] = {
.snd_device = NULL,
.net_device = NULL
},
/* This has the UMC 88xx on-chip KBC. All the copies of the BIOS string I can find, end in
in -H, so the UMC on-chip KBC likely emulates the AMI 'H' KBC firmware. */
{
.name = "[UMC 8881] Biostar MB-84xxUUD-A",
.internal_name = "84xxuuda",
.type = MACHINE_TYPE_486_S3_PCI,
.chipset = MACHINE_CHIPSET_UMC_UM8881,
.init = machine_at_84xxuuda_init,
.p1_handler = NULL,
.gpio_handler = NULL,
.available_flag = MACHINE_AVAILABLE,
.gpio_acpi_handler = NULL,
.cpu = {
.package = CPU_PKG_SOCKET3,
.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_PCI,
.flags = MACHINE_IDE_DUAL | MACHINE_APM,
.ram = {
.min = 1024,
.max = 131072,
.step = 1024
},
.nvrmask = 255,
.kbc_device = NULL,
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.snd_device = NULL,
.net_device = NULL
},
/* This has an AMIKey-2, which is an updated version of type 'H'. */
{
.name = "[UMC 8881] ECS Elite UM8810P-AIO",
@@ -9112,7 +9236,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.vid_device = &tgui9440_onboard_pci_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -9153,7 +9277,7 @@ const machine_t machines[] = {
.device = NULL,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,
.vid_device = &gd5430_onboard_pci_device,
.snd_device = NULL,
.net_device = NULL
},
@@ -9259,7 +9383,7 @@ const machine_t machines[] = {
.min_multi = 0,
.max_multi = 0
},
.bus_flags = MACHINE_PCI,
.bus_flags = MACHINE_PS2_PCI,
.flags = MACHINE_IDE_DUAL | MACHINE_APM,
.ram = {
.min = 1024,
@@ -9271,7 +9395,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &hot433a_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,

View File

@@ -291,8 +291,12 @@ net_slirp_get_revents(int idx, void *opaque)
WSA_TO_POLL(FD_WRITE, SLIRP_POLL_OUT);
WSA_TO_POLL(FD_CONNECT, SLIRP_POLL_OUT);
WSA_TO_POLL(FD_OOB, SLIRP_POLL_PRI);
WSA_TO_POLL(FD_CLOSE, SLIRP_POLL_IN);
WSA_TO_POLL(FD_CLOSE, SLIRP_POLL_HUP);
if (ret == 0)
ret |= SLIRP_POLL_IN;
return ret;
}
#else

View File

@@ -638,6 +638,25 @@ pic_reset_hard(void)
}
}
void
pic_toggle_latch(int is_ps2)
{
pic_kbd_latch(0x00);
pic_mouse_latch(0x00);
/* Explicitly reset the latches. */
kbd_latch = mouse_latch = 0;
latched_irqs = 0x0000;
/* The situation is as follows: There is a giant mess when it comes to these latches on real hardware,
to the point that there's even boards with board-level latched that get used in place of the latches
on the chipset, therefore, I'm just doing this here for the sake of simplicity. */
if (is_ps2) {
pic_kbd_latch(0x01);
pic_mouse_latch(0x01);
}
}
void
pic_init(void)
{

View File

@@ -598,7 +598,10 @@ msgid "ISA RTC:"
msgstr "ISA RTC:"
msgid "ISA Memory Expansion"
msgstr "Карта расширения памяти ISA"
msgstr "Карты расширения памяти ISA"
msgid "ISA ROM Cards"
msgstr "Карты ПЗУ ISA"
msgid "Card 1:"
msgstr "Карта 1:"
@@ -1237,7 +1240,7 @@ msgid "Pen"
msgstr "Ручка"
msgid "Host CD/DVD Drive (%1:)"
msgstr "CD/DVD-привод хоста (%1:)"
msgstr "CD/DVD Привод хоста (%1:)"
msgid "&Connected"
msgstr "&Кабель подключен"
@@ -1249,7 +1252,7 @@ msgid "Create..."
msgstr "Создать..."
msgid "Host CD/DVD Drive (%1)"
msgstr "CD/DVD-привод хоста (%1)"
msgstr "CD/DVD Привод хоста (%1)"
msgid "Unknown Bus"
msgstr "Неизвестная шина"
@@ -1413,12 +1416,54 @@ msgstr "Системный MIDI"
msgid "MIDI Input Device"
msgstr "Устройство ввода MIDI"
msgid "BIOS file"
msgstr "Файл BIOS"
msgid "BIOS file (ROM #1)"
msgstr "Файл BIOS (ПЗУ #1)"
msgid "BIOS file (ROM #2)"
msgstr "Файл BIOS (ПЗУ #2)"
msgid "BIOS file (ROM #3)"
msgstr "Файл BIOS (ПЗУ #3)"
msgid "BIOS file (ROM #4)"
msgstr "Файл BIOS (ПЗУ #4)"
msgid "BIOS Address"
msgstr "Адрес BIOS"
msgid "BIOS address (ROM #1)"
msgstr "Адрес BIOS (ПЗУ #1)"
msgid "BIOS address (ROM #2)"
msgstr "Адрес BIOS (ПЗУ #2)"
msgid "BIOS address (ROM #3)"
msgstr "Адрес BIOS (ПЗУ #3)"
msgid "BIOS address (ROM #4)"
msgstr "Адрес BIOS (ПЗУ #4)"
msgid "Enable BIOS extension ROM Writes"
msgstr "Разрешить запись в ПЗУ расширения BIOS"
msgid "Enable BIOS extension ROM Writes (ROM #1)"
msgstr "Разрешить запись в ПЗУ расширения BIOS (ПЗУ #1)"
msgid "Enable BIOS extension ROM Writes (ROM #2)"
msgstr "Разрешить запись в ПЗУ расширения BIOS (ПЗУ #2)"
msgid "Enable BIOS extension ROM Writes (ROM #3)"
msgstr "Разрешить запись в ПЗУ расширения BIOS (ПЗУ #3)"
msgid "Enable BIOS extension ROM Writes (ROM #4)"
msgstr "Разрешить запись в ПЗУ расширения BIOS (ПЗУ #4)"
msgid "Linear framebuffer base"
msgstr "Линейная база кадрового буфера"
msgid "Address"
msgstr "Адрес"
@@ -1428,6 +1473,21 @@ msgstr "IRQ"
msgid "BIOS Revision"
msgstr "Версия BIOS"
msgid "BIOS Version"
msgstr "Версия BIOS"
msgid "BIOS Versions"
msgstr "Версии BIOS"
msgid "BIOS Language"
msgstr "Язык BIOS"
msgid "IBM 5161 Expansion Unit"
msgstr "Блок расширения IBM 5161"
msgid "IBM Cassette Basic"
msgstr "Кассетный бейсик IBM"
msgid "Translate 26 -> 17"
msgstr "Переводить 26 -> 17"
@@ -1443,6 +1503,18 @@ msgstr "Инвертировать цвета"
msgid "BIOS size"
msgstr "Размер BIOS"
msgid "BIOS size (ROM #1)"
msgstr "Размер BIOS (ПЗУ #1)"
msgid "BIOS size (ROM #2)"
msgstr "Размер BIOS (ПЗУ #2)"
msgid "BIOS size (ROM #3)"
msgstr "Размер BIOS (ПЗУ #3)"
msgid "BIOS size (ROM #4)"
msgstr "Размер BIOS (ПЗУ #4)"
msgid "Map C0000-C7FFF as UMB"
msgstr "Отображение C0000-C7FFF в качестве UMB"
@@ -1518,6 +1590,9 @@ msgstr "Уровень реверберации"
msgid "Interpolation Method"
msgstr "Метод интерполяции"
msgid "Dynamic Sample Loading"
msgstr "Динамическая загрузка сэмплов"
msgid "Reverb Output Gain"
msgstr "Усиление выходного сигнала ревербератора"
@@ -1606,7 +1681,7 @@ msgid "Enable Game port"
msgstr "Включить игровой порт"
msgid "Surround module"
msgstr "Модуль объемного звучания"
msgstr "Модуль объёмного звучания"
msgid "CODEC"
msgstr "Кодек"
@@ -1617,6 +1692,9 @@ msgstr "Поднимать прерывание кодека при настро
msgid "SB Address"
msgstr "Адрес SB"
msgid "Use EEPROM setting"
msgstr "Использовать настройку EEPROM"
msgid "WSS IRQ"
msgstr "IRQ WSS"
@@ -1701,6 +1779,9 @@ msgstr "Тип RAMDAC"
msgid "Blend"
msgstr "Смесь"
msgid "Font"
msgstr "Шрифт"
msgid "Bilinear filtering"
msgstr "Билинейная фильтрация"
@@ -1746,6 +1827,33 @@ msgstr "Скорость передачи данных"
msgid "EMS mode"
msgstr "Режим EMS"
msgid "EMS Address"
msgstr "Адрес EMS"
msgid "EMS 1 Address"
msgstr "Адрес EMS 1"
msgid "EMS 2 Address"
msgstr "Адрес EMS 2"
msgid "EMS Memory Size"
msgstr "Размер памяти EMS"
msgid "EMS 1 Memory Size"
msgstr "Размер памяти EMS 1"
msgid "EMS 2 Memory Size"
msgstr "Размер памяти EMS 2"
msgid "Enable EMS"
msgstr "Включить EMS"
msgid "Enable EMS 1"
msgstr "Включить EMS 1"
msgid "Enable EMS 2"
msgstr "Включить EMS 2"
msgid "Address for > 2 MB"
msgstr "Адрес для > 2 МБ"
@@ -1765,10 +1873,10 @@ msgid "BIOS setting + Hotkeys (off during POST)"
msgstr "Настройка BIOS + горячие клавиши (отключается во время POST)"
msgid "64 kB starting from F0000"
msgstr "64 кБ, начиная с F0000"
msgstr "64 КБ, начиная с F0000"
msgid "128 kB starting from E0000 (address MSB inverted, last 64KB first)"
msgstr "128 кБ, начиная с E0000 (адрес MSB инвертирован, сначала последние 64 КБ)"
msgstr "128 КБ, начиная с E0000 (адрес MSB инвертирован, сначала последние 64 КБ)"
msgid "Sine"
msgstr "Синусоидальная"
@@ -1792,7 +1900,7 @@ msgid "45 Hz (JMP2 not populated)"
msgstr "45 Гц (без джампера на JMP2)"
msgid "Two"
msgstr "Два"
msgstr "Две"
msgid "Three"
msgstr "Три"
@@ -1935,6 +2043,9 @@ msgstr "Янтарный"
msgid "Gray"
msgstr "Серый"
msgid "Grayscale"
msgstr "Монохромный"
msgid "Color"
msgstr "Цветной"
@@ -1950,6 +2061,12 @@ msgstr "Другие языки"
msgid "Bochs latest"
msgstr "Bochs последний"
msgid "Apply overscan deltas"
msgstr "Применить дельты вылетов развёртки"
msgid "Mono Interlaced"
msgstr "Монохромный с чересстрочной развёрткой"
msgid "Mono Non-Interlaced"
msgstr "Монохромный без чересстрочной развёртки"
@@ -2095,7 +2212,7 @@ msgid "TrueType fonts in the \"roms/printer/fonts\" directory are required for t
msgstr "Шрифты TrueType в каталоге \"roms/printer/fonts\" необходимы для эмуляции стандартного матричного принтера ESC/P."
msgid "Inhibit multimedia keys"
msgstr "Перехватывать мультимедиа-клавиши"
msgstr "Перехватывать мультимедийные клавиши"
msgid "Ask for confirmation before saving settings"
msgstr "Запрашивать подтверждение перед сохранением настроек"
@@ -2182,7 +2299,7 @@ msgid "Send Control+Alt+Escape"
msgstr "Отправить Control+Alt+Escape"
msgid "Toggle fullscreen"
msgstr "Переключить на полноэкранный режим"
msgstr "Переключить полноэкранный режим"
msgid "Screenshot"
msgstr "Скриншот"

View File

@@ -216,7 +216,7 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
(GetForegroundWindow() == ((HWND) secondaryRenderer->winId())));
}
bool skip = ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window);
bool skip = ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window || (kbd_req_capture && !mouse_capture));
if (skip)
return CallNextHookEx(NULL, nCode, wParam, lParam);

View File

@@ -11,75 +11,134 @@
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2020-2021 David Hrdlička.
# Copyright 2025 starfrost
#
add_library(vid OBJECT
# Video Core
agpgart.c
video.c
vid_table.c
# RAMDAC (Should this be its own library?)
ramdac/vid_ramdac_ati68860.c
ramdac/vid_ramdac_ati68875.c
ramdac/vid_ramdac_att20c49x.c
ramdac/vid_ramdac_att2xc498.c
ramdac/vid_ramdac_bt48x.c
ramdac/vid_ramdac_bt481.c
ramdac/vid_ramdac_ibm_rgb528.c
ramdac/vid_ramdac_sc1148x.c
ramdac/vid_ramdac_sc1502x.c
ramdac/vid_ramdac_sdac.c
ramdac/vid_ramdac_stg1702.c
ramdac/vid_ramdac_tkd8001.c
ramdac/vid_ramdac_tvp3026.c
# Clock generator chips
clockgen/vid_clockgen_av9194.c
clockgen/vid_clockgen_icd2061.c
clockgen/vid_clockgen_ics2494.c
clockgen/vid_clockgen_ics2595.c
# DDC / monitor identification stuff
vid_ddc.c
# CARDS start here
# CGA / Super CGA
vid_cga.c
vid_cga_comp.c
vid_compaq_cga.c
vid_cga_compaq.c
vid_cga_compaq_plasma.c
vid_cga_colorplus.c
vid_cga_ncr.c
vid_cga_olivetti.c
vid_cga_toshiba_t1000.c
vid_cga_toshiba_t3100e.c
# PCJr/Tandy
vid_pcjr.c
vid_tandy.c
vid_mda.c
# Hercules
vid_hercules.c
vid_herculesplus.c
vid_incolor.c
vid_colorplus.c
vid_hercules_plus.c
vid_hercules_incolor.c
# Other early CGA-era cards
vid_genius.c
vid_sigma.c
# PGC / IM1024 / WY700 high-resolution
vid_pgc.c
vid_im1024.c
vid_sigma.c
vid_wy700.c
# EGA
vid_ega.c
vid_ega_render.c
vid_svga.c
vid_8514a.c
vid_svga_render.c
vid_ddc.c
vid_jega.c
# (Real IBM) VGA
vid_vga.c
# Super VGA core
vid_svga.c
vid_svga_render.c
# 8514/A, XGA and derivatives
vid_8514a.c
vid_xga.c
vid_ps55da2.c
# ATI Technologies
vid_ati_eeprom.c
vid_ati18800.c
vid_ati28800.c
vid_ati_mach8.c
vid_ati_mach64.c
vid_ati68875_ramdac.c
vid_ati68860_ramdac.c
vid_bt481_ramdac.c
vid_bt48x_ramdac.c
# Chips & Technologies
vid_chips_69000.c
vid_av9194.c
vid_icd2061.c
vid_ics2494.c
vid_ics2595.c
# Cirrus Logic
vid_cl54xx.c
# Tseng Labs
vid_et3000.c
vid_et4000.c
vid_sc1148x_ramdac.c
vid_sc1502x_ramdac.c
vid_et4000w32.c
vid_stg_ramdac.c
# Headland
vid_ht216.c
vid_oak_oti.c
# Paradise
vid_paradise.c
vid_rtg310x.c
vid_f82c425.c
vid_ti_cf62011.c
vid_tvga.c vid_tgui9440.c
vid_tkd8001_ramdac.c
vid_att20c49x_ramdac.c
vid_s3.c vid_s3_virge.c
vid_ibm_rgb528_ramdac.c
vid_sdac_ramdac.c
vid_ogc.c
# Trident
vid_tvga.c
vid_tgui9440.c
# S3 Graphics
vid_s3.c
vid_s3_virge.c
# Matrox
vid_mga.c
vid_nga.c
vid_tvp3026_ramdac.c
vid_att2xc498_ramdac.c
vid_xga.c
vid_bochs_vbe.c
vid_ps55da2.c
vid_jega.c
# NVidia (pending)
nv/nv_rivatimer.c
# Generic
vid_bochs_vbe.c
)
if(G100)
@@ -90,6 +149,7 @@ if(XL24)
target_compile_definitions(vid PRIVATE USE_XL24)
endif()
# 3Dfx Voodoo
add_library(voodoo OBJECT
vid_voodoo.c
vid_voodoo_banshee.c

View File

@@ -261,38 +261,57 @@ void
ati68860_hwcursor_draw(svga_t *svga, int displine)
{
const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac;
int comb;
int offset;
uint8_t dat;
int x_pos;
int y_pos;
int shift = 0;
uint16_t dat;
uint32_t col0 = ramdac->pallook[0];
uint32_t col1 = ramdac->pallook[1];
uint32_t *p;
offset = svga->dac_hwcursor_latch.xoff;
for (uint32_t x = 0; x < 64 - svga->dac_hwcursor_latch.xoff; x += 4) {
dat = svga->vram[svga->dac_hwcursor_latch.addr + (offset >> 2)];
if (!(dat & 2))
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3)
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF;
dat >>= 2;
if (!(dat & 2))
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3)
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF;
dat >>= 2;
if (!(dat & 2))
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3)
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF;
dat >>= 2;
if (!(dat & 2))
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0;
else if ((dat & 3) == 3)
buffer32->line[displine][svga->dac_hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF;
dat >>= 2;
offset += 4;
offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff;
if (svga->packed_4bpp)
shift = 1;
for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += (8 >> shift)) {
if (shift) {
dat = svga->vram[(svga->dac_hwcursor_latch.addr) & svga->vram_mask] & 0x0f;
dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 1) & svga->vram_mask] << 4);
dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 2) & svga->vram_mask] << 8);
dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 3) & svga->vram_mask] << 12);
} else {
dat = svga->vram[svga->dac_hwcursor_latch.addr & svga->vram_mask];
dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 1) & svga->vram_mask] << 8);
}
for (int xx = 0; xx < (8 >> shift); xx++) {
comb = (dat >> (xx << 1)) & 0x03;
y_pos = displine;
x_pos = offset + svga->x_add;
p = buffer32->line[y_pos];
if (offset >= svga->dac_hwcursor_latch.x) {
switch (comb) {
case 0:
p[x_pos] = col0;
break;
case 1:
p[x_pos] = col1;
break;
case 3:
p[x_pos] ^= 0xffffff;
break;
default:
break;
}
}
offset++;
}
svga->dac_hwcursor_latch.addr += 2;
}
svga->dac_hwcursor_latch.addr += 16;
}
static void

View File

@@ -104,7 +104,7 @@ ibm_rgb528_render_4bpp(svga_t *svga)
if ((svga->displine + svga->y_add) < 0)
return;
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) {
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
if (svga->firstline_draw == 2000)
@@ -114,8 +114,8 @@ ibm_rgb528_render_4bpp(svga_t *svga)
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
if (vram_size == 3) {
if (!(x & 31)) {
dat64 = *(uint64_t *) (&svga->vram[svga->ma]);
dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]);
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]);
if (swap_word) {
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL);
@@ -127,7 +127,7 @@ ibm_rgb528_render_4bpp(svga_t *svga)
dat = (((x & 16) ? dat642 : dat64) >> (((x & 15) << 2) ^ 4)) & 0xf;
} else if (vram_size == 1) {
if (!(x & 15)) {
dat64 = *(uint64_t *) (&svga->vram[svga->ma]);
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
if (swap_word)
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
}
@@ -137,7 +137,7 @@ ibm_rgb528_render_4bpp(svga_t *svga)
dat = (dat64 >> (((x & 15) << 2) ^ 4)) & 0xf;
} else {
if (!(x & 7))
dat32 = *(uint32_t *) (&svga->vram[svga->ma]);
dat32 = *(uint32_t *) (&svga->vram[svga->memaddr]);
if (swap_nib)
dat = (dat32 >> ((x & 7) << 2)) & 0xf;
else
@@ -156,11 +156,11 @@ ibm_rgb528_render_4bpp(svga_t *svga)
p[x] = dat_out.pixel & 0xffffff;
if ((vram_size == 3) && ((x & 31) == 31))
svga->ma = (svga->ma + 16) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask;
if ((vram_size == 1) && ((x & 15) == 15))
svga->ma = (svga->ma + 8) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask;
else if ((!vram_size) && ((x & 7) == 7))
svga->ma = (svga->ma + 4) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask;
}
}
}
@@ -182,7 +182,7 @@ ibm_rgb528_render_8bpp(svga_t *svga)
if ((svga->displine + svga->y_add) < 0)
return;
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) {
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
if (svga->firstline_draw == 2000)
@@ -192,8 +192,8 @@ ibm_rgb528_render_8bpp(svga_t *svga)
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
if (vram_size == 3) {
if (!(x & 15)) {
dat64 = *(uint64_t *) (&svga->vram[svga->ma]);
dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]);
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]);
if (swap_word) {
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL);
@@ -202,14 +202,14 @@ ibm_rgb528_render_8bpp(svga_t *svga)
dat = (((x & 8) ? dat642 : dat64) >> ((x & 7) << 3)) & 0xff;
} else if (vram_size == 1) {
if (!(x & 7)) {
dat64 = *(uint64_t *) (&svga->vram[svga->ma]);
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
if (swap_word)
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
}
dat = (dat64 >> ((x & 7) << 3)) & 0xff;
} else {
if (!(x & 3))
dat32 = *(uint32_t *) (&svga->vram[svga->ma]);
dat32 = *(uint32_t *) (&svga->vram[svga->memaddr]);
dat = (dat32 >> ((x & 3) << 3)) & 0xff;
}
if (b8_dcol == 0x00) {
@@ -225,11 +225,11 @@ ibm_rgb528_render_8bpp(svga_t *svga)
p[x] = dat_out.pixel & 0xffffff;
if ((vram_size == 3) && ((x & 15) == 15))
svga->ma = (svga->ma + 16) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask;
else if ((vram_size == 1) && ((x & 7) == 7))
svga->ma = (svga->ma + 8) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask;
else if ((!vram_size) && ((x & 3) == 3))
svga->ma = (svga->ma + 4) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask;
}
}
}
@@ -262,7 +262,7 @@ ibm_rgb528_render_15_16bpp(svga_t *svga)
if (b555_565 && (b16_dcol != 0x01))
partition &= 0xc0;
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) {
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
if (svga->firstline_draw == 2000)
@@ -272,8 +272,8 @@ ibm_rgb528_render_15_16bpp(svga_t *svga)
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
if (vram_size == 2) {
if (!(x & 7)) {
dat64 = *(uint64_t *) (&svga->vram[svga->ma]);
dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]);
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]);
if (swap_word) {
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
dat642 = (dat64 << 32ULL) | (dat642 >> 32ULL);
@@ -282,14 +282,14 @@ ibm_rgb528_render_15_16bpp(svga_t *svga)
dat = (((x & 4) ? dat642 : dat64) >> ((x & 3) << 4)) & 0xffff;
} else if (vram_size == 1) {
if (!(x & 3)) {
dat64 = *(uint64_t *) (&svga->vram[svga->ma]);
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
if (swap_word)
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
}
dat = (dat64 >> ((x & 3) << 4)) & 0xffff;
} else {
if (!(x & 1))
dat32 = *(uint32_t *) (&svga->vram[svga->ma]);
dat32 = *(uint32_t *) (&svga->vram[svga->memaddr]);
dat = (dat32 >> ((x & 1) << 4)) & 0xffff;
}
dat_ex = (ibm_rgb528_pixel16_t *) &dat;
@@ -350,11 +350,11 @@ ibm_rgb528_render_15_16bpp(svga_t *svga)
p[x] = dat_out.pixel & 0xffffff;
if ((vram_size == 3) && ((x & 7) == 7))
svga->ma = (svga->ma + 16) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask;
else if ((vram_size == 1) && ((x & 3) == 3))
svga->ma = (svga->ma + 8) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask;
else if (!vram_size && ((x & 1) == 1))
svga->ma = (svga->ma + 4) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask;
}
}
}
@@ -378,7 +378,7 @@ ibm_rgb528_render_24bpp(svga_t *svga)
if ((svga->displine + svga->y_add) < 0)
return;
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) {
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
if (svga->firstline_draw == 2000)
@@ -389,12 +389,12 @@ ibm_rgb528_render_24bpp(svga_t *svga)
dat_ex = (ibm_rgb528_pixel32_t *) &dat;
if (vram_size == 3) {
if ((x & 15) == 0) {
dat64[0] = *(uint64_t *) (&svga->vram[svga->ma & svga->vram_display_mask]);
dat64[1] = *(uint64_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);
dat64[2] = *(uint64_t *) (&svga->vram[(svga->ma + 16) & svga->vram_display_mask]);
dat64[3] = *(uint64_t *) (&svga->vram[(svga->ma + 24) & svga->vram_display_mask]);
dat64[4] = *(uint64_t *) (&svga->vram[(svga->ma + 32) & svga->vram_display_mask]);
dat64[5] = *(uint64_t *) (&svga->vram[(svga->ma + 40) & svga->vram_display_mask]);
dat64[0] = *(uint64_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]);
dat64[1] = *(uint64_t *) (&svga->vram[(svga->memaddr + 8) & svga->vram_display_mask]);
dat64[2] = *(uint64_t *) (&svga->vram[(svga->memaddr + 16) & svga->vram_display_mask]);
dat64[3] = *(uint64_t *) (&svga->vram[(svga->memaddr + 24) & svga->vram_display_mask]);
dat64[4] = *(uint64_t *) (&svga->vram[(svga->memaddr + 32) & svga->vram_display_mask]);
dat64[5] = *(uint64_t *) (&svga->vram[(svga->memaddr + 40) & svga->vram_display_mask]);
if (swap_word) {
dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL);
dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL);
@@ -407,9 +407,9 @@ ibm_rgb528_render_24bpp(svga_t *svga)
dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[(x & 15) * 3]);
} else if (vram_size == 1) {
if ((x & 7) == 0) {
dat64[0] = *(uint64_t *) (&svga->vram[svga->ma & svga->vram_display_mask]);
dat64[1] = *(uint64_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);
dat64[2] = *(uint64_t *) (&svga->vram[(svga->ma + 16) & svga->vram_display_mask]);
dat64[0] = *(uint64_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]);
dat64[1] = *(uint64_t *) (&svga->vram[(svga->memaddr + 8) & svga->vram_display_mask]);
dat64[2] = *(uint64_t *) (&svga->vram[(svga->memaddr + 16) & svga->vram_display_mask]);
if (swap_word) {
dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL);
dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL);
@@ -441,9 +441,9 @@ ibm_rgb528_render_24bpp(svga_t *svga)
p[x] = dat_ex->pixel & 0xffffff;
if ((vram_size == 3) && ((x & 15) == 15))
svga->ma = (svga->ma + 48) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 48) & svga->vram_display_mask;
else if ((vram_size == 1) && ((x & 7) == 7))
svga->ma = (svga->ma + 24) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 24) & svga->vram_display_mask;
}
}
}
@@ -468,7 +468,7 @@ ibm_rgb528_render_32bpp(svga_t *svga)
if ((svga->displine + svga->y_add) < 0)
return;
if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) {
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
if (svga->firstline_draw == 2000)
@@ -478,8 +478,8 @@ ibm_rgb528_render_32bpp(svga_t *svga)
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
if (vram_size == 3) {
if (!(x & 3)) {
dat64 = *(uint64_t *) (&svga->vram[svga->ma]);
dat642 = *(uint64_t *) (&svga->vram[svga->ma + 8]);
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]);
if (swap_word) {
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL);
@@ -488,13 +488,13 @@ ibm_rgb528_render_32bpp(svga_t *svga)
dat = (((x & 2) ? dat642 : dat64) >> ((x & 1ULL) << 5ULL)) & 0xffffffff;
} else if (vram_size == 1) {
if (!(x & 1)) {
dat64 = *(uint64_t *) (&svga->vram[svga->ma]);
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
if (swap_word)
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
}
dat = (dat64 >> ((x & 1ULL) << 5ULL)) & 0xffffffff;
} else
dat = *(uint32_t *) (&svga->vram[svga->ma]);
dat = *(uint32_t *) (&svga->vram[svga->memaddr]);
dat_ex = (ibm_rgb528_pixel32_t *) &dat;
if (swaprb) {
temp = dat_ex->r;
@@ -520,11 +520,11 @@ ibm_rgb528_render_32bpp(svga_t *svga)
p[x] = dat_ex->pixel & 0xffffff;
if ((vram_size == 3) && ((x & 3) == 3))
svga->ma = (svga->ma + 16) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask;
else if ((vram_size == 1) && ((x & 1) == 1))
svga->ma = (svga->ma + 8) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask;
else if (!vram_size)
svga->ma = (svga->ma + 4) & svga->vram_display_mask;
svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask;
}
}
}

View File

@@ -459,7 +459,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len)
break;
case 0x42e8:
ibm8514_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val);
ibm8514_log("VBLANK status=%02x, val=%02x.\n", dev->subsys_stat, val);
if (len == 2) {
dev->subsys_cntl = val;
dev->subsys_stat &= ~val;
@@ -3383,7 +3383,7 @@ ibm8514_render_8bpp(svga_t *svga)
if ((dev->displine + svga->y_add) < 0)
return;
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) {
if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
if (dev->firstline_draw == 2000)
@@ -3391,22 +3391,22 @@ ibm8514_render_8bpp(svga_t *svga)
dev->lastline_draw = dev->displine;
for (int x = 0; x <= dev->h_disp; x += 8) {
dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]);
p[0] = dev->pallook[dat & dev->dac_mask & 0xff];
p[1] = dev->pallook[(dat >> 8) & dev->dac_mask & 0xff];
p[2] = dev->pallook[(dat >> 16) & dev->dac_mask & 0xff];
p[3] = dev->pallook[(dat >> 24) & dev->dac_mask & 0xff];
dat = *(uint32_t *) (&dev->vram[(dev->ma + 4) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 4) & dev->vram_mask]);
p[4] = dev->pallook[dat & dev->dac_mask & 0xff];
p[5] = dev->pallook[(dat >> 8) & dev->dac_mask & 0xff];
p[6] = dev->pallook[(dat >> 16) & dev->dac_mask & 0xff];
p[7] = dev->pallook[(dat >> 24) & dev->dac_mask & 0xff];
dev->ma += 8;
dev->memaddr += 8;
p += 8;
}
dev->ma &= dev->vram_mask;
dev->memaddr &= dev->vram_mask;
}
}
@@ -3421,7 +3421,7 @@ ibm8514_render_15bpp(svga_t *svga)
if ((dev->displine + svga->y_add) < 0)
return;
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) {
if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
if (dev->firstline_draw == 2000)
@@ -3429,24 +3429,24 @@ ibm8514_render_15bpp(svga_t *svga)
dev->lastline_draw = dev->displine;
for (x = 0; x <= dev->h_disp; x += 8) {
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1)) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1)) & dev->vram_mask]);
p[x] = video_15to32[dat & 0xffff];
p[x + 1] = video_15to32[dat >> 16];
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 4) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 4) & dev->vram_mask]);
p[x + 2] = video_15to32[dat & 0xffff];
p[x + 3] = video_15to32[dat >> 16];
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 8) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 8) & dev->vram_mask]);
p[x + 4] = video_15to32[dat & 0xffff];
p[x + 5] = video_15to32[dat >> 16];
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 12) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 12) & dev->vram_mask]);
p[x + 6] = video_15to32[dat & 0xffff];
p[x + 7] = video_15to32[dat >> 16];
}
dev->ma += (x << 1);
dev->ma &= dev->vram_mask;
dev->memaddr += (x << 1);
dev->memaddr &= dev->vram_mask;
}
}
@@ -3461,7 +3461,7 @@ ibm8514_render_16bpp(svga_t *svga)
if ((dev->displine + svga->y_add) < 0)
return;
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) {
if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
if (dev->firstline_draw == 2000)
@@ -3469,24 +3469,24 @@ ibm8514_render_16bpp(svga_t *svga)
dev->lastline_draw = dev->displine;
for (x = 0; x <= dev->h_disp; x += 8) {
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1)) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1)) & dev->vram_mask]);
p[x] = video_16to32[dat & 0xffff];
p[x + 1] = video_16to32[dat >> 16];
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 4) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 4) & dev->vram_mask]);
p[x + 2] = video_16to32[dat & 0xffff];
p[x + 3] = video_16to32[dat >> 16];
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 8) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 8) & dev->vram_mask]);
p[x + 4] = video_16to32[dat & 0xffff];
p[x + 5] = video_16to32[dat >> 16];
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 1) + 12) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 1) + 12) & dev->vram_mask]);
p[x + 6] = video_16to32[dat & 0xffff];
p[x + 7] = video_16to32[dat >> 16];
}
dev->ma += (x << 1);
dev->ma &= dev->vram_mask;
dev->memaddr += (x << 1);
dev->memaddr &= dev->vram_mask;
}
}
@@ -3500,7 +3500,7 @@ ibm8514_render_24bpp(svga_t *svga)
if ((dev->displine + svga->y_add) < 0)
return;
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) {
if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
if (dev->firstline_draw == 2000)
@@ -3508,21 +3508,21 @@ ibm8514_render_24bpp(svga_t *svga)
dev->lastline_draw = dev->displine;
for (int x = 0; x <= dev->h_disp; x += 4) {
dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]);
p[x] = dat & 0xffffff;
dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 3) & dev->vram_mask]);
p[x + 1] = dat & 0xffffff;
dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 6) & dev->vram_mask]);
p[x + 2] = dat & 0xffffff;
dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 9) & dev->vram_mask]);
p[x + 3] = dat & 0xffffff;
dev->ma += 12;
dev->memaddr += 12;
}
dev->ma &= dev->vram_mask;
dev->memaddr &= dev->vram_mask;
}
}
@@ -3536,7 +3536,7 @@ ibm8514_render_BGR(svga_t *svga)
if ((dev->displine + svga->y_add) < 0)
return;
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) {
if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
if (dev->firstline_draw == 2000)
@@ -3544,21 +3544,21 @@ ibm8514_render_BGR(svga_t *svga)
dev->lastline_draw = dev->displine;
for (int x = 0; x <= dev->h_disp; x += 4) {
dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]);
p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 3) & dev->vram_mask]);
p[x + 1] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 6) & dev->vram_mask]);
p[x + 2] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 9) & dev->vram_mask]);
p[x + 3] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
dev->ma += 12;
dev->memaddr += 12;
}
dev->ma &= dev->vram_mask;
dev->memaddr &= dev->vram_mask;
}
}
@@ -3573,7 +3573,7 @@ ibm8514_render_ABGR8888(svga_t *svga)
if ((dev->displine + svga->y_add) < 0)
return;
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) {
if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
if (dev->firstline_draw == 2000)
@@ -3581,11 +3581,11 @@ ibm8514_render_ABGR8888(svga_t *svga)
dev->lastline_draw = dev->displine;
for (x = 0; x <= dev->h_disp; x++) {
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 2)) & dev->vram_mask]);
*p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
}
dev->ma += (x * 4);
dev->ma &= dev->vram_mask;
dev->memaddr += (x * 4);
dev->memaddr &= dev->vram_mask;
}
}
@@ -3600,7 +3600,7 @@ ibm8514_render_32bpp(svga_t *svga)
if ((dev->displine + svga->y_add) < 0)
return;
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || dev->changedvram[(dev->ma >> 12) + 2] || svga->fullchange) {
if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || dev->changedvram[(dev->memaddr >> 12) + 2] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
if (dev->firstline_draw == 2000)
@@ -3608,11 +3608,11 @@ ibm8514_render_32bpp(svga_t *svga)
dev->lastline_draw = dev->displine;
for (x = 0; x <= dev->h_disp; x++) {
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 2)) & dev->vram_mask]);
p[x] = dat & 0xffffff;
}
dev->ma += (x * 4);
dev->ma &= dev->vram_mask;
dev->memaddr += (x * 4);
dev->memaddr &= dev->vram_mask;
}
}
@@ -3681,7 +3681,7 @@ ibm8514_poll(void *priv)
if (dev->dispon) {
dev->hdisp_on = 1;
dev->ma &= dev->vram_mask;
dev->memaddr &= dev->vram_mask;
if (dev->firstline == 2000) {
dev->firstline = dev->displine;
@@ -3689,14 +3689,14 @@ ibm8514_poll(void *priv)
}
if (dev->hwcursor_on)
dev->changedvram[dev->ma >> 12] = dev->changedvram[(dev->ma >> 12) + 1] = dev->interlace ? 3 : 2;
dev->changedvram[dev->memaddr >> 12] = dev->changedvram[(dev->memaddr >> 12) + 1] = dev->interlace ? 3 : 2;
svga->render8514(svga);
svga->x_add = (overscan_x >> 1);
svga->x_add = svga->left_overscan;
ibm8514_render_overscan_left(dev, svga);
ibm8514_render_overscan_right(dev, svga);
svga->x_add = (overscan_x >> 1);
svga->x_add = svga->left_overscan;
if (dev->hwcursor_on) {
if (svga->hwcursor_draw)
@@ -3726,18 +3726,18 @@ ibm8514_poll(void *priv)
dev->linepos = 0;
if (dev->dispon) {
if (dev->sc == dev->rowcount) {
dev->sc = 0;
dev->maback += (dev->rowoffset << 3);
if (dev->scanline == dev->rowcount) {
dev->scanline = 0;
dev->memaddr_backup += (dev->rowoffset << 3);
if (dev->interlace)
dev->maback += (dev->rowoffset << 3);
dev->memaddr_backup += (dev->rowoffset << 3);
dev->maback &= dev->vram_mask;
dev->ma = dev->maback;
dev->memaddr_backup &= dev->vram_mask;
dev->memaddr = dev->memaddr_backup;
} else {
dev->sc++;
dev->sc &= 0x1f;
dev->ma = dev->maback;
dev->scanline++;
dev->scanline &= 0x1f;
dev->memaddr = dev->memaddr_backup;
}
}
@@ -3783,20 +3783,20 @@ ibm8514_poll(void *priv)
svga->vslines = 0;
if (dev->interlace && dev->oddeven)
dev->ma = dev->maback = (dev->rowoffset << 1);
dev->memaddr = dev->memaddr_backup = (dev->rowoffset << 1);
else
dev->ma = dev->maback = 0;
dev->memaddr = dev->memaddr_backup = 0;
dev->ma = (dev->ma << 2);
dev->maback = (dev->maback << 2);
dev->memaddr = (dev->memaddr << 2);
dev->memaddr_backup = (dev->memaddr_backup << 2);
}
if (dev->vc == dev->v_total) {
dev->vc = 0;
dev->sc = (svga->crtc[0x8] & 0x1f);
dev->scanline = (svga->crtc[0x8] & 0x1f);
dev->dispon = 1;
dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0;
svga->x_add = (overscan_x >> 1);
svga->x_add = svga->left_overscan;
dev->hwcursor_on = 0;
dev->hwcursor_latch = dev->hwcursor;
@@ -3966,7 +3966,7 @@ ibm8514_init(const device_t *info)
bios_addr = 0xc6000;
switch (dev->extensions) {
case 1:
case ATI:
if (rom_present(BIOS_MACH8_ROM_PATH)) {
mach_t * mach = (mach_t *) calloc(1, sizeof(mach_t));
svga->ext8514 = mach;
@@ -3977,13 +3977,14 @@ ibm8514_init(const device_t *info)
0, MEM_MAPPING_EXTERNAL);
ati8514_init(svga, svga->ext8514, svga->dev8514);
mach->accel.scratch0 = ((((bios_addr >> 7) - 0x1000) >> 4));
mach->accel.scratch0 = ((bios_addr >> 7) - 0x1000) >> 4;
bios_rom_eeprom = mach->accel.scratch0;
if (dev->type & DEVICE_MCA) {
dev->pos_regs[0] = 0x88;
dev->pos_regs[1] = 0x80;
mach->eeprom.data[0] = 0x0000;
mach->eeprom.data[1] = bios_rom_eeprom | ((bios_rom_eeprom | 0x01) << 8);
ibm8514_log("EEPROM Data1=%04x.\n", mach->eeprom.data[1]);
mca_add(ati8514_mca_read, ati8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga);
ati_eeprom_load_mach8(&mach->eeprom, "ati8514_mca.nvr", 1);
mem_mapping_disable(&dev->bios_rom.mapping);
@@ -4067,12 +4068,12 @@ static const device_config_t isa_ext8514_config[] = {
.description = "Vendor",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 0,
.default_int = IBM,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "IBM", .value = 0 },
{ .description = "ATI", .value = 1 },
{ .description = "IBM", .value = IBM },
{ .description = "ATI", .value = ATI },
{ .description = "" }
},
.bios = { { 0 } }
@@ -4127,12 +4128,12 @@ static const device_config_t mca_ext8514_config[] = {
.description = "Vendor",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 0,
.default_int = IBM,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "IBM", .value = 0 },
{ .description = "ATI", .value = 1 },
{ .description = "IBM", .value = IBM },
{ .description = "ATI", .value = ATI },
{ .description = "" }
},
.bios = { { 0 } }
@@ -4145,7 +4146,7 @@ const device_t gen8514_isa_device = {
.name = "IBM 8514/A clone (ISA)",
.internal_name = "8514_isa",
.flags = DEVICE_ISA16,
.local = 0,
.local = IBM_8514A_TYPE,
.init = ibm8514_init,
.close = ibm8514_close,
.reset = NULL,
@@ -4159,7 +4160,7 @@ const device_t ibm8514_mca_device = {
.name = "IBM 8514/A (MCA)",
.internal_name = "8514_mca",
.flags = DEVICE_MCA,
.local = 0,
.local = IBM_8514A_TYPE,
.init = ibm8514_init,
.close = ibm8514_close,
.reset = NULL,

View File

@@ -109,7 +109,7 @@ ati18800_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
@@ -223,7 +223,7 @@ ati18800_recalctimings(svga_t *svga)
else {
svga->render = svga_render_8bpp_highres;
if (!svga->packed_4bpp) {
svga->ma_latch <<= 1;
svga->memaddr_latch <<= 1;
svga->rowoffset <<= 1;
}
}

View File

@@ -206,7 +206,7 @@ ati28800_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
@@ -416,10 +416,10 @@ ati28800_recalctimings(svga_t *svga)
((ati28800->regs[0xb9] & 2) << 1);
if (ati28800->regs[0xa3] & 0x10)
svga->ma_latch |= 0x10000;
svga->memaddr_latch |= 0x10000;
if (ati28800->regs[0xb0] & 0x40)
svga->ma_latch |= 0x20000;
svga->memaddr_latch |= 0x20000;
if (ati28800->regs[0xb8] & 0x40)
svga->clock *= 2;
@@ -483,7 +483,7 @@ ati28800_recalctimings(svga_t *svga)
else {
svga->render = svga_render_8bpp_highres;
if (!svga->packed_4bpp) {
svga->ma_latch <<= 1;
svga->memaddr_latch <<= 1;
svga->rowoffset <<= 1;
}
}
@@ -496,7 +496,7 @@ ati28800_recalctimings(svga_t *svga)
svga->hdisp >>= 1;
svga->dots_per_clock >>= 1;
svga->rowoffset <<= 1;
svga->ma_latch <<= 1;
svga->memaddr_latch <<= 1;
}
break;
default:

View File

@@ -456,7 +456,7 @@ mach64_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = svga->monitor->mon_changeframecount;
svga_recalctimings(svga);
@@ -524,14 +524,18 @@ mach64_recalctimings(svga_t *svga)
svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1;
svga->rowoffset = (mach64->crtc_off_pitch >> 22);
svga->clock = (cpuclock * (double) (1ULL << 32)) / ics2595_getclock(svga->clock_gen);
svga->ma_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2;
svga->memaddr_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2;
svga->linedbl = svga->rowcount = 0;
svga->split = 0xffffff;
svga->vblankstart = svga->dispend;
svga->rowcount = mach64->crtc_gen_cntl & 1;
svga->rowoffset <<= 1;
if (mach64->type == MACH64_GX)
ati68860_ramdac_set_render(svga->ramdac, svga);
svga->packed_4bpp = !!(((mach64->crtc_gen_cntl >> 8) & 7) == BPP_4);
switch ((mach64->crtc_gen_cntl >> 8) & 7) {
case BPP_4:
if (mach64->type != MACH64_GX)
@@ -572,8 +576,9 @@ mach64_recalctimings(svga_t *svga)
}
svga->vram_display_mask = mach64->vram_mask;
} else
} else {
svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff;
}
}
void
@@ -2310,6 +2315,7 @@ uint8_t
mach64_ext_readb(uint32_t addr, void *priv)
{
mach64_t *mach64 = (mach64_t *) priv;
svga_t *svga = &mach64->svga;
uint8_t ret = 0xff;
if (!(addr & 0x400)) {
@@ -2524,8 +2530,22 @@ mach64_ext_readb(uint32_t addr, void *priv)
case 0xc3:
if (mach64->type == MACH64_GX)
ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga);
else
ret = ati68860_ramdac_in(addr & 3, mach64->svga.ramdac, &mach64->svga);
else {
switch (addr & 3) {
case 0:
ret = svga_in(0x3c8, svga);
break;
case 1:
ret = svga_in(0x3c9, svga);
break;
case 2:
ret = svga_in(0x3c6, svga);
break;
case 3:
ret = svga_in(0x3c7, svga);
break;
}
}
break;
case 0xc4:
case 0xc5:
@@ -2962,7 +2982,7 @@ mach64_ext_readl(uint32_t addr, void *priv)
uint32_t ret;
if (!(addr & 0x400)) {
mach64_log("nmach64_ext_readl: addr=%04x\n", addr);
mach64_log("mach64_ext_readl: addr=%04x\n", addr);
ret = 0xffffffff;
} else
switch (addr & 0x3ff) {
@@ -3101,6 +3121,7 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv)
} else if (addr & 0x300) {
mach64_queue(mach64, addr & 0x3ff, val, FIFO_WRITE_BYTE);
} else {
mach64_log("mach64_ext_writeb: addr=%04x val=%02x\n", addr & 0x3ff, val);
switch (addr & 0x3ff) {
case 0x00:
case 0x01:
@@ -3189,39 +3210,48 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv)
case 0x62:
case 0x63:
WRITE8(addr, mach64->cur_clr0, val);
if (mach64->type == MACH64_VT2)
ati68860_ramdac_set_pallook(mach64->svga.ramdac, 0, makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff));
break;
case 0x64:
case 0x65:
case 0x66:
case 0x67:
WRITE8(addr, mach64->cur_clr1, val);
if (mach64->type == MACH64_VT2)
ati68860_ramdac_set_pallook(mach64->svga.ramdac, 1, makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff));
break;
case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
WRITE8(addr, mach64->cur_offset, val);
svga->dac_hwcursor.addr = (mach64->cur_offset & 0xfffff) * 8;
if (mach64->type == MACH64_GX)
svga->dac_hwcursor.addr = (mach64->cur_offset & 0xfffff) << 3;
else
svga->hwcursor.addr = (mach64->cur_offset & 0xfffff) << 3;
break;
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
WRITE8(addr, mach64->cur_horz_vert_posn, val);
svga->dac_hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff;
svga->dac_hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff;
if (mach64->type == MACH64_GX) {
svga->dac_hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff;
svga->dac_hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff;
} else {
svga->hwcursor.x = mach64->cur_horz_vert_posn & 0x7ff;
svga->hwcursor.y = (mach64->cur_horz_vert_posn >> 16) & 0x7ff;
}
break;
case 0x70:
case 0x71:
case 0x72:
case 0x73:
WRITE8(addr, mach64->cur_horz_vert_off, val);
svga->dac_hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f;
svga->dac_hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f;
if (mach64->type == MACH64_GX) {
svga->dac_hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f;
svga->dac_hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f;
} else {
svga->hwcursor.xoff = mach64->cur_horz_vert_off & 0x3f;
svga->hwcursor.yoff = (mach64->cur_horz_vert_off >> 16) & 0x3f;
}
break;
case 0x80:
@@ -3283,8 +3313,22 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv)
case 0xc3:
if (mach64->type == MACH64_GX)
ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga);
else
ati68860_ramdac_out(addr & 3, val, svga->ramdac, svga);
else {
switch (addr & 3) {
case 0:
svga_out(0x3c8, val, svga);
break;
case 1:
svga_out(0x3c9, val, svga);
break;
case 2:
svga_out(0x3c6, val, svga);
break;
case 3:
svga_out(0x3c7, val, svga);
break;
}
}
break;
case 0xc4:
case 0xc5:
@@ -3294,7 +3338,8 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv)
mach64_log("Ext RAMDAC TYPE write=%x, bit set=%03x.\n", addr & 0x3ff, mach64->dac_cntl & 0x100);
if ((addr & 3) >= 1) {
svga_set_ramdac_type(svga, !!(mach64->dac_cntl & 0x100));
ati68860_set_ramdac_type(svga->ramdac, !!(mach64->dac_cntl & 0x100));
if (mach64->type == MACH64_GX)
ati68860_set_ramdac_type(svga->ramdac, !!(mach64->dac_cntl & 0x100));
}
i2c_gpio_set(mach64->i2c, !(mach64->dac_cntl & 0x20000000) || (mach64->dac_cntl & 0x04000000), !(mach64->dac_cntl & 0x10000000) || (mach64->dac_cntl & 0x02000000));
break;
@@ -3306,7 +3351,10 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv)
WRITE8(addr, mach64->gen_test_cntl, val);
ati_eeprom_write(&mach64->eeprom, mach64->gen_test_cntl & 0x10, mach64->gen_test_cntl & 2, mach64->gen_test_cntl & 1);
mach64->gen_test_cntl = (mach64->gen_test_cntl & ~8) | (ati_eeprom_read(&mach64->eeprom) ? 8 : 0);
svga->dac_hwcursor.ena = mach64->gen_test_cntl & 0x80;
if (mach64->type == MACH64_GX)
svga->dac_hwcursor.ena = !!(mach64->gen_test_cntl & 0x80);
else
svga->hwcursor.ena = !!(mach64->gen_test_cntl & 0x80);
break;
case 0xdc:
@@ -3371,6 +3419,7 @@ uint8_t
mach64_ext_inb(uint16_t port, void *priv)
{
mach64_t *mach64 = (mach64_t *) priv;
svga_t *svga = &mach64->svga;
uint8_t ret = 0xff;
switch (port) {
@@ -3384,6 +3433,12 @@ mach64_ext_inb(uint16_t port, void *priv)
case 0x7eef:
ret = mach64_ext_readb(0x400 | 0x00 | (port & 3), priv);
break;
case 0x06ec:
case 0x06ed:
case 0x06ee:
case 0x06ef:
ret = mach64_ext_readb(0x400 | 0x04 | (port & 3), priv);
break;
case 0x0aec:
case 0x0aed:
case 0x0aee:
@@ -3519,8 +3574,22 @@ mach64_ext_inb(uint16_t port, void *priv)
case 0x5eef:
if (mach64->type == MACH64_GX)
ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga);
else
ret = ati68860_ramdac_in(port & 3, mach64->svga.ramdac, &mach64->svga);
else {
switch (port & 3) {
case 0:
ret = svga_in(0x3c8, svga);
break;
case 1:
ret = svga_in(0x3c9, svga);
break;
case 2:
ret = svga_in(0x3c6, svga);
break;
case 3:
ret = svga_in(0x3c7, svga);
break;
}
}
break;
case 0x62ec:
@@ -3617,6 +3686,12 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv)
case 0x7eef:
mach64_ext_writeb(0x400 | 0x00 | (port & 3), val, priv);
break;
case 0x06ec:
case 0x06ed:
case 0x06ee:
case 0x06ef:
mach64_ext_writeb(0x400 | 0x04 | (port & 3), val, priv);
break;
case 0x0aec:
case 0x0aed:
case 0x0aee:
@@ -3745,8 +3820,22 @@ mach64_ext_outb(uint16_t port, uint8_t val, void *priv)
case 0x5eef:
if (mach64->type == MACH64_GX)
ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga);
else
ati68860_ramdac_out(port & 3, val, svga->ramdac, svga);
else {
switch (port & 3) {
case 0:
svga_out(0x3c8, val, svga);
break;
case 1:
svga_out(0x3c9, val, svga);
break;
case 2:
svga_out(0x3c6, val, svga);
break;
case 3:
svga_out(0x3c7, val, svga);
break;
}
}
break;
case 0x62ec:
@@ -3905,6 +3994,63 @@ mach64_readl(uint32_t addr, void *priv)
return ret;
}
void
mach64_int_hwcursor_draw(svga_t *svga, int displine)
{
const mach64_t *mach64 = (mach64_t *) svga->priv;
int comb;
int offset;
int x_pos;
int y_pos;
int shift = 0;
uint16_t dat;
uint32_t col0 = makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff);
uint32_t col1 = makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff);
uint32_t *p;
offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
if (svga->packed_4bpp)
shift = 1;
for (int x = 0; x < svga->hwcursor_latch.cur_xsize; x += (8 >> shift)) {
if (shift) {
dat = svga->vram[(svga->hwcursor_latch.addr) & svga->vram_mask] & 0x0f;
dat |= (svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_mask] << 4);
dat |= (svga->vram[(svga->hwcursor_latch.addr + 2) & svga->vram_mask] << 8);
dat |= (svga->vram[(svga->hwcursor_latch.addr + 3) & svga->vram_mask] << 12);
} else {
dat = svga->vram[svga->hwcursor_latch.addr & svga->vram_mask];
dat |= (svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_mask] << 8);
}
for (int xx = 0; xx < (8 >> shift); xx++) {
comb = (dat >> (xx << 1)) & 0x03;
y_pos = displine;
x_pos = offset + svga->x_add;
p = buffer32->line[y_pos];
if (offset >= svga->hwcursor_latch.x) {
switch (comb) {
case 0:
p[x_pos] = col0;
break;
case 1:
p[x_pos] = col1;
break;
case 3:
p[x_pos] ^= 0xffffff;
break;
default:
break;
}
}
offset++;
}
svga->hwcursor_latch.addr += 2;
}
}
#define CLAMP(x) \
do { \
if ((x) & ~0xff) \
@@ -4550,15 +4696,22 @@ mach64_common_init(const device_t *info)
svga = &mach64->svga;
mach64->type = info->local & 0xff;
mach64->vram_size = device_get_config_int("memory");
mach64->vram_mask = (mach64->vram_size << 20) - 1;
svga_init(info, svga, mach64, mach64->vram_size << 20,
mach64_recalctimings,
mach64_in, mach64_out,
NULL,
mach64_overlay_draw);
svga->dac_hwcursor.cur_ysize = 64;
if (mach64->type > MACH64_GX)
svga_init(info, svga, mach64, mach64->vram_size << 20,
mach64_recalctimings,
mach64_in, mach64_out,
mach64_int_hwcursor_draw,
mach64_overlay_draw);
else
svga_init(info, svga, mach64, mach64->vram_size << 20,
mach64_recalctimings,
mach64_in, mach64_out,
NULL,
mach64_overlay_draw);
mem_mapping_add(&mach64->linear_mapping, 0, 0, mach64_read_linear, mach64_readw_linear, mach64_readl_linear, mach64_write_linear, mach64_writew_linear, mach64_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga);
mem_mapping_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64);
@@ -4576,9 +4729,6 @@ mach64_common_init(const device_t *info)
mach64->pci_regs[0x32] = 0x0c;
mach64->pci_regs[0x33] = 0x00;
svga->ramdac = device_add(&ati68860_ramdac_device);
svga->dac_hwcursor_draw = ati68860_hwcursor_draw;
svga->clock_gen = device_add(&ics2595_device);
mach64->dst_cntl = 3;
@@ -4598,6 +4748,13 @@ static void *
mach64gx_init(const device_t *info)
{
mach64_t *mach64 = mach64_common_init(info);
svga_t *svga = &mach64->svga;
svga->ramdac = device_add(&ati68860_ramdac_device);
svga->dac_hwcursor_draw = ati68860_hwcursor_draw;
svga->dac_hwcursor.cur_ysize = 64;
svga->dac_hwcursor.cur_xsize = 64;
if (info->flags & DEVICE_ISA16)
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_isa);
@@ -4606,12 +4763,11 @@ mach64gx_init(const device_t *info)
else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_vlb);
mach64->type = MACH64_GX;
mach64->pci = !!(info->flags & DEVICE_PCI);
mach64->pci_id = 'X' | ('G' << 8);
mach64->config_chip_id = 0x000000d7;
mach64->dac_cntl = 5 << 16; /*ATI 68860 RAMDAC*/
mach64->config_stat0 = (5 << 9) | (3 << 3); /*ATI-68860, 256Kx16 DRAM*/
mach64->config_stat0 = (5 << 9) | (3 << 3); /*ATI 68860, 256Kx16 DRAM*/
if (info->flags & DEVICE_PCI) {
mach64->config_stat0 |= 7; /*PCI, 256Kx16 DRAM*/
ati_eeprom_load(&mach64->eeprom, "mach64_pci.nvr", 1);
@@ -4635,9 +4791,13 @@ mach64vt2_init(const device_t *info)
mach64_t *mach64 = mach64_common_init(info);
svga_t *svga = &mach64->svga;
svga->dac_hwcursor_draw = NULL;
svga->hwcursor.cur_ysize = 64;
svga->hwcursor.cur_xsize = 64;
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_mach64_pci);
mach64->type = MACH64_VT2;
mach64->pci = 1;
mach64->pci_id = 0x5654;
mach64->config_chip_id = 0x40005654;
@@ -4757,7 +4917,7 @@ const device_t mach64gx_isa_device = {
.name = "ATI Mach64GX ISA",
.internal_name = "mach64gx_isa",
.flags = DEVICE_ISA16,
.local = 0,
.local = MACH64_GX,
.init = mach64gx_init,
.close = mach64_close,
.reset = NULL,
@@ -4771,7 +4931,7 @@ const device_t mach64gx_vlb_device = {
.name = "ATI Mach64GX VLB",
.internal_name = "mach64gx_vlb",
.flags = DEVICE_VLB,
.local = 0,
.local = MACH64_GX,
.init = mach64gx_init,
.close = mach64_close,
.reset = NULL,
@@ -4785,7 +4945,7 @@ const device_t mach64gx_pci_device = {
.name = "ATI Mach64GX PCI",
.internal_name = "mach64gx_pci",
.flags = DEVICE_PCI,
.local = 0,
.local = MACH64_GX,
.init = mach64gx_init,
.close = mach64_close,
.reset = NULL,
@@ -4799,7 +4959,7 @@ const device_t mach64vt2_device = {
.name = "ATI Mach64VT2",
.internal_name = "mach64vt2",
.flags = DEVICE_PCI,
.local = 0,
.local = MACH64_VT2,
.init = mach64vt2_init,
.close = mach64_close,
.reset = NULL,

View File

@@ -817,6 +817,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3
dev->accel.dy |= ~0x5ff;
/*Destination Width*/
mach->accel.dx_first_row_start = dev->accel.cur_x;
if (dev->accel.cur_x >= 0x600)
mach->accel.dx_first_row_start |= ~0x5ff;
mach->accel.dx_start = mach->accel.dest_x_start;
if (mach->accel.dest_x_start >= 0x600)
mach->accel.dx_start |= ~0x5ff;
@@ -831,16 +835,9 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3
} else if (mach->accel.dx_end < mach->accel.dx_start) {
mach->accel.width = (mach->accel.dx_start - mach->accel.dx_end);
mach->accel.stepx = -1;
if (dev->accel.dx > 0)
dev->accel.dx--;
mach_log("BitBLT: Dst Negative X, dxstart = %d, end = %d, width = %d, dx = %d, dpconfig = %04x.\n",
mach->accel.dest_x_start, mach->accel.dest_x_end, mach->accel.width, dev->accel.dx,
mach->accel.dp_config);
} else {
mach->accel.stepx = 1;
mach->accel.width = 0;
mach_log("BitBLT: Dst Indeterminate X, dpconfig = %04x, destxend = %d, destxstart = %d.\n",
mach->accel.dp_config, mach->accel.dest_x_end, mach->accel.dest_x_start);
}
dev->accel.sx = 0;
@@ -869,6 +866,24 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3
if (mach->accel.dp_config == 0x4011)
mach->accel.height++;
if (mach->accel.height == 1) {
if (mach->accel.dx_end > mach->accel.dx_first_row_start) {
mach->accel.width = (mach->accel.dx_end - mach->accel.dx_first_row_start);
mach->accel.stepx = 1;
} else if (mach->accel.dx_end < mach->accel.dx_first_row_start) {
mach->accel.width = (mach->accel.dx_first_row_start - mach->accel.dx_end);
mach->accel.stepx = -1;
} else {
mach->accel.stepx = 1;
mach->accel.width = 0;
}
}
if (mach->accel.stepx == -1) {
if (dev->accel.dx > 0)
dev->accel.dx--;
}
dev->accel.sy = 0;
dev->accel.dest = mach->accel.dst_ge_offset + (dev->accel.dy * mach->accel.dst_pitch);
@@ -2461,7 +2476,7 @@ mach_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = svga->monitor->mon_changeframecount;
svga_recalctimings(svga);
@@ -2604,7 +2619,7 @@ ati_render_24bpp(svga_t *svga)
if ((dev->displine + svga->y_add) < 0)
return;
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || svga->fullchange) {
if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
if (dev->firstline_draw == 2000)
@@ -2613,38 +2628,38 @@ ati_render_24bpp(svga_t *svga)
if (mach->accel.ext_ge_config & 0x400) { /*BGR, Blue-(23:16), Green-(15:8), Red-(7:0)*/
for (int x = 0; x <= dev->h_disp; x += 4) {
dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]);
p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 3) & dev->vram_mask]);
p[x + 1] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 6) & dev->vram_mask]);
p[x + 2] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 9) & dev->vram_mask]);
p[x + 3] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
dev->ma += 12;
dev->memaddr += 12;
}
} else { /*RGB, Red-(23:16), Green-(15:8), Blue-(7:0)*/
for (int x = 0; x <= dev->h_disp; x += 4) {
dat = *(uint32_t *) (&dev->vram[dev->ma & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[dev->memaddr & dev->vram_mask]);
p[x] = dat & 0xffffff;
dat = *(uint32_t *) (&dev->vram[(dev->ma + 3) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 3) & dev->vram_mask]);
p[x + 1] = dat & 0xffffff;
dat = *(uint32_t *) (&dev->vram[(dev->ma + 6) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 6) & dev->vram_mask]);
p[x + 2] = dat & 0xffffff;
dat = *(uint32_t *) (&dev->vram[(dev->ma + 9) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + 9) & dev->vram_mask]);
p[x + 3] = dat & 0xffffff;
dev->ma += 12;
dev->memaddr += 12;
}
}
dev->ma &= dev->vram_mask;
dev->memaddr &= dev->vram_mask;
}
}
@@ -2660,7 +2675,7 @@ ati_render_32bpp(svga_t *svga)
if ((dev->displine + svga->y_add) < 0)
return;
if (dev->changedvram[dev->ma >> 12] || dev->changedvram[(dev->ma >> 12) + 1] || dev->changedvram[(dev->ma >> 12) + 2] || svga->fullchange) {
if (dev->changedvram[dev->memaddr >> 12] || dev->changedvram[(dev->memaddr >> 12) + 1] || dev->changedvram[(dev->memaddr >> 12) + 2] || svga->fullchange) {
p = &buffer32->line[dev->displine + svga->y_add][svga->x_add];
if (dev->firstline_draw == 2000)
@@ -2669,17 +2684,17 @@ ati_render_32bpp(svga_t *svga)
if (mach->accel.ext_ge_config & 0x400) { /*BGR, Blue-(23:16), Green-(15:8), Red-(7:0)*/
for (x = 0; x <= dev->h_disp; x++) {
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 2)) & dev->vram_mask]);
*p++ = ((dat & 0x00ff0000) >> 16) | (dat & 0x0000ff00) | ((dat & 0x000000ff) << 16);
}
} else { /*RGB, Red-(31:24), Green-(23:16), Blue-(15:8)*/
for (x = 0; x <= dev->h_disp; x++) {
dat = *(uint32_t *) (&dev->vram[(dev->ma + (x << 2)) & dev->vram_mask]);
dat = *(uint32_t *) (&dev->vram[(dev->memaddr + (x << 2)) & dev->vram_mask]);
*p++ = ((dat & 0xffffff00) >> 8);
}
}
dev->ma += (x * 4);
dev->ma &= dev->vram_mask;
dev->memaddr += (x * 4);
dev->memaddr &= dev->vram_mask;
}
}
@@ -2847,17 +2862,17 @@ mach_recalctimings(svga_t *svga)
if (ATI_MACH32) {
if (mach->regs[0xad] & 0x04)
svga->ma_latch |= 0x40000;
svga->memaddr_latch |= 0x40000;
if (mach->regs[0xad] & 0x08)
svga->ma_latch |= 0x80000;
svga->memaddr_latch |= 0x80000;
}
if (mach->regs[0xa3] & 0x10)
svga->ma_latch |= 0x10000;
svga->memaddr_latch |= 0x10000;
if (mach->regs[0xb0] & 0x40)
svga->ma_latch |= 0x20000;
svga->memaddr_latch |= 0x20000;
if ((mach->regs[0xb6] & 0x18) >= 0x10) {
svga->hdisp <<= 1;
@@ -2886,7 +2901,7 @@ mach_recalctimings(svga_t *svga)
mach_log("ON=%d, override=%d, gelo=%04x, gehi=%04x, vgahdisp=%d.\n", dev->on, svga->override, mach->accel.ge_offset_lo, mach->accel.ge_offset_hi, svga->hdisp);
if (dev->on) {
dev->ma_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/
dev->memaddr_latch = 0; /*(mach->accel.crt_offset_lo | (mach->accel.crt_offset_hi << 16)) << 2;*/
dev->interlace = !!(dev->disp_cntl & 0x10);
dev->pitch = dev->ext_pitch;
dev->rowoffset = dev->ext_crt_pitch;
@@ -3085,7 +3100,7 @@ mach_recalctimings(svga_t *svga)
else {
svga->render = svga_render_8bpp_highres;
if (!svga->packed_4bpp) {
svga->ma_latch <<= 1;
svga->memaddr_latch <<= 1;
svga->rowoffset <<= 1;
}
}
@@ -3297,7 +3312,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u
case 0x42e8:
case 0x42e9:
mach_log("VBLANK stat=%02x, val=%02x.\n", dev->subsys_stat, val);
mach_log("VBLANK status=%02x, val=%02x.\n", dev->subsys_stat, val);
if (len == 2)
dev->subsys_cntl = val;
else {
@@ -3972,7 +3987,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u
break;
case 0x92ee:
mach_log("Write port 92ee, malatch=%08x.\n", svga->ma_latch);
mach_log("Write port 92ee, malatch=%08x.\n", svga->memaddr_latch);
break;
case 0x96ee:
@@ -4227,7 +4242,7 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u
break;
default:
mach_log("Unknown or reserved write to %04x, val=%04x, len=%d, latch=%08x.\n", port, val, len, svga->ma_latch);
mach_log("Unknown or reserved write to %04x, val=%04x, len=%d, latch=%08x.\n", port, val, len, svga->memaddr_latch);
break;
}
}
@@ -6475,6 +6490,7 @@ ati8514_io_set(svga_t *svga)
io_sethandler(0xeeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga);
io_sethandler(0xf2ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga);
io_sethandler(0xf6ee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga);
io_sethandler(0xfaee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga);
io_sethandler(0xfeee, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga);
}
@@ -7409,7 +7425,7 @@ const device_t mach8_vga_isa_device = {
.name = "ATI Mach8 (ATI Graphics Ultra) (ISA)",
.internal_name = "mach8_vga_isa",
.flags = DEVICE_ISA,
.local = 1,
.local = ATI_38800_TYPE,
.init = mach8_init,
.close = mach_close,
.reset = mach_reset,
@@ -7423,7 +7439,7 @@ const device_t mach32_isa_device = {
.name = "ATI Mach32 (ISA)",
.internal_name = "mach32_isa",
.flags = DEVICE_ISA,
.local = 2,
.local = ATI_68800_TYPE,
.init = mach8_init,
.close = mach_close,
.reset = mach_reset,
@@ -7437,7 +7453,7 @@ const device_t mach32_vlb_device = {
.name = "ATI Mach32 (VLB)",
.internal_name = "mach32_vlb",
.flags = DEVICE_VLB,
.local = 2,
.local = ATI_68800_TYPE,
.init = mach8_init,
.close = mach_close,
.reset = mach_reset,
@@ -7451,7 +7467,7 @@ const device_t mach32_mca_device = {
.name = "ATI Mach32 (MCA)",
.internal_name = "mach32_mca",
.flags = DEVICE_MCA,
.local = 2,
.local = ATI_68800_TYPE,
.init = mach8_init,
.close = mach_close,
.reset = mach_reset,
@@ -7465,7 +7481,7 @@ const device_t mach32_pci_device = {
.name = "ATI Mach32 (PCI)",
.internal_name = "mach32_pci",
.flags = DEVICE_PCI,
.local = 2,
.local = ATI_68800_TYPE,
.init = mach8_init,
.close = mach_close,
.reset = mach_reset,
@@ -7479,7 +7495,7 @@ const device_t mach32_onboard_pci_device = {
.name = "ATI Mach32 (PCI) On-Board",
.internal_name = "mach32_pci_onboard",
.flags = DEVICE_PCI,
.local = 2 | 0x100,
.local = ATI_68800_TYPE | 0x100,
.init = mach8_init,
.close = mach_close,
.reset = mach_reset,

View File

@@ -336,13 +336,13 @@ bochs_vbe_recalctimings(svga_t* svga)
if (svga->bpp == 4) {
svga->rowoffset = (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] / 2) >> 3;
svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) +
svga->memaddr_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) +
(dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3);
svga->fullchange = 3;
} else {
svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8));
svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) +
svga->memaddr_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) +
(dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)));
svga->fullchange = 3;
}
@@ -470,11 +470,11 @@ bochs_vbe_outw(const uint16_t addr, const uint16_t val, void *priv)
svga_t *svga = &dev->svga;
if (svga->bpp == 4) {
svga->rowoffset = (dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] / 2) >> 3;
svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) +
svga->memaddr_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) +
(dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] >> 3);
} else {
svga->rowoffset = dev->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8));
svga->ma_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) +
svga->memaddr_latch = (dev->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] * svga->rowoffset) +
(dev->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] * ((svga->bpp == 15) ? 2 : (svga->bpp / 8)));
}
@@ -575,7 +575,7 @@ bochs_vbe_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);

View File

@@ -73,10 +73,10 @@ void cga_recalctimings(cga_t *cga);
static void
cga_update_latch(cga_t *cga)
{
uint32_t lp_latch = cga->displine * cga->crtc[1];
uint32_t lp_latch = cga->displine * cga->crtc[CGA_CRTC_HDISP];
cga->crtc[0x10] = (lp_latch >> 8) & 0x3f;
cga->crtc[0x11] = lp_latch & 0xff;
cga->crtc[CGA_CRTC_LIGHT_PEN_ADDR_HIGH] = (lp_latch >> 8) & 0x3f;
cga->crtc[CGA_CRTC_LIGHT_PEN_ADDR_LOW] = lp_latch & 0xff;
}
void
@@ -89,20 +89,22 @@ cga_out(uint16_t addr, uint8_t val, void *priv)
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x3D4:
case CGA_REGISTER_CRTC_INDEX:
cga->crtcreg = val & 31;
return;
case 0x3D5:
case CGA_REGISTER_CRTC_DATA:
old = cga->crtc[cga->crtcreg];
cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg];
if (old != val) {
// Recalc the timings if we are writing any invalid CRTC register or a valid CRTC register
// except the CURSOR and LIGHT PEN registers
if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x11)) {
cga->fullchange = changeframecount;
cga_recalctimings(cga);
}
}
return;
case 0x3D8:
case CGA_REGISTER_MODE_CONTROL:
old = cga->cgamode;
cga->cgamode = val;
@@ -113,18 +115,18 @@ cga_out(uint16_t addr, uint8_t val, void *priv)
cga_recalctimings(cga);
}
return;
case 0x3D9:
case CGA_REGISTER_COLOR_SELECT:
old = cga->cgacol;
cga->cgacol = val;
if (old ^ val)
cga_recalctimings(cga);
return;
case 0x3DB:
case CGA_REGISTER_CLEAR_LIGHT_PEN_LATCH:
if (cga->lp_strobe == 1)
cga->lp_strobe = 0;
return;
case 0x3DC:
case CGA_REGISTER_SET_LIGHT_PEN_LATCH:
if (cga->lp_strobe == 0) {
cga->lp_strobe = 1;
cga_update_latch(cga);
@@ -146,21 +148,20 @@ cga_in(uint16_t addr, void *priv)
addr = (addr & 0xff9) | 0x004;
switch (addr) {
case 0x3D4:
case CGA_REGISTER_CRTC_INDEX:
ret = cga->crtcreg;
break;
case 0x3D5:
case CGA_REGISTER_CRTC_DATA:
ret = cga->crtc[cga->crtcreg];
break;
case 0x3DA:
case CGA_REGISTER_STATUS:
ret = cga->cgastat;
break;
case 0x3DB:
case CGA_REGISTER_CLEAR_LIGHT_PEN_LATCH:
if (cga->lp_strobe == 1)
cga->lp_strobe = 0;
break;
case 0x3DC:
case CGA_REGISTER_SET_LIGHT_PEN_LATCH:
if (cga->lp_strobe == 0) {
cga->lp_strobe = 1;
cga_update_latch(cga);
@@ -235,12 +236,12 @@ cga_recalctimings(cga_t *cga)
double _dispontime;
double _dispofftime;
if (cga->cgamode & 1) {
disptime = (double) (cga->crtc[0] + 1);
_dispontime = (double) cga->crtc[1];
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
disptime = (double) (cga->crtc[CGA_CRTC_HTOTAL] + 1);
_dispontime = (double) cga->crtc[CGA_CRTC_HDISP];
} else {
disptime = (double) ((cga->crtc[0] + 1) << 1);
_dispontime = (double) (cga->crtc[1] << 1);
disptime = (double) ((cga->crtc[CGA_CRTC_HTOTAL] + 1) << 1);
_dispontime = (double) (cga->crtc[CGA_CRTC_HDISP] << 1);
}
_dispofftime = disptime - _dispontime;
_dispontime = _dispontime * CGACONST;
@@ -252,95 +253,97 @@ cga_recalctimings(cga_t *cga)
static void
cga_render(cga_t *cga, int line)
{
uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (cga->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (cga->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
int column;
uint8_t chr;
uint8_t attr;
uint16_t dat;
int cols[4];
int col;
if ((cga->cgamode & 0x12) == 0x12) {
for (c = 0; c < 8; ++c) {
buffer32->line[line][c] = 0;
if (cga->cgamode & 1)
buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = 0;
int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
if (((cga->cgamode & highres_graphics_flag) == highres_graphics_flag)) {
for (column = 0; column < 8; ++column) {
buffer32->line[line][column] = 0;
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
buffer32->line[line][column + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = 0;
else
buffer32->line[line][c + (cga->crtc[1] << 4) + 8] = 0;
buffer32->line[line][column + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = 0;
}
} else {
for (c = 0; c < 8; ++c) {
buffer32->line[line][c] = (cga->cgacol & 15) + 16;
if (cga->cgamode & 1)
buffer32->line[line][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16;
for (column = 0; column < 8; ++column) {
buffer32->line[line][column] = (cga->cgacol & 15) + 16;
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
buffer32->line[line][column + (cga->crtc[CGA_CRTC_HDISP] << 3) + 8] = (cga->cgacol & 15) + 16;
else
buffer32->line[line][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16;
buffer32->line[line][column + (cga->crtc[CGA_CRTC_HDISP] << 4) + 8] = (cga->cgacol & 15) + 16;
}
}
if (cga->cgamode & 1) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8) {
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
chr = cga->charbuffer[x << 1];
attr = cga->charbuffer[(x << 1) + 1];
} else
chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron);
cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) {
if (cga->cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor)
cols[1] = cols[0];
} else
cols[0] = (attr >> 4) + 16;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[line][(x << 3) + c + 8]
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
for (column = 0; column < 8; column++) {
buffer32->line[line][(x << 3) + column + 8]
= cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[line][(x << 3) + c + 8]
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
for (column = 0; column < 8; column++) {
buffer32->line[line][(x << 3) + column + 8]
= cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0];
}
}
cga->ma++;
cga->memaddr++;
}
} else if (!(cga->cgamode & 2)) {
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8) {
chr = cga->vram[(cga->ma << 1) & 0x3fff];
attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff];
} else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
chr = cga->vram[(cga->memaddr << 1) & 0x3fff];
attr = cga->vram[((cga->memaddr << 1) + 1) & 0x3fff];
} else
chr = attr = 0;
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
drawcursor = ((cga->memaddr == cursoraddr) && cga->cursorvisible && cga->cursoron);
cols[1] = (attr & 15) + 16;
if (cga->cgamode & 0x20) {
if (cga->cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((cga->cgablink & 8) && (attr & 0x80))
cols[1] = cols[0];
} else
cols[0] = (attr >> 4) + 16;
cga->ma++;
cga->memaddr++;
if (drawcursor) {
for (c = 0; c < 8; c++) {
buffer32->line[line][(x << 4) + (c << 1) + 8]
= buffer32->line[line][(x << 4) + (c << 1) + 9]
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
for (column = 0; column < 8; column++) {
buffer32->line[line][(x << 4) + (column << 1) + 8]
= buffer32->line[line][(x << 4) + (column << 1) + 9]
= cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0] ^ 15;
}
} else {
for (c = 0; c < 8; c++) {
buffer32->line[line][(x << 4) + (c << 1) + 8]
= buffer32->line[line][(x << 4) + (c << 1) + 9]
= cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0];
for (column = 0; column < 8; column++) {
buffer32->line[line][(x << 4) + (column << 1) + 8]
= buffer32->line[line][(x << 4) + (column << 1) + 9]
= cols[(fontdat[chr + cga->fontbase][cga->scanline & 7] & (1 << (column ^ 7))) ? 1 : 0];
}
}
}
} else if (!(cga->cgamode & 16)) {
} else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
cols[0] = (cga->cgacol & 15) | 16;
col = (cga->cgacol & 16) ? 24 : 16;
if (cga->cgamode & 4) {
if (cga->cgamode & CGA_MODE_FLAG_BW) {
cols[1] = col | 3; /* Cyan */
cols[2] = col | 4; /* Red */
cols[3] = col | 7; /* White */
@@ -353,16 +356,16 @@ cga_render(cga_t *cga, int line)
cols[2] = col | 4; /* Red */
cols[3] = col | 6; /* Yellow */
}
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) |
cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE)
dat = (cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000)] << 8) |
cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000) + 1];
else
dat = 0;
cga->ma++;
for (c = 0; c < 8; c++) {
buffer32->line[line][(x << 4) + (c << 1) + 8]
= buffer32->line[line][(x << 4) + (c << 1) + 9]
cga->memaddr++;
for (column = 0; column < 8; column++) {
buffer32->line[line][(x << 4) + (column << 1) + 8]
= buffer32->line[line][(x << 4) + (column << 1) + 9]
= cols[dat >> 14];
dat <<= 2;
}
@@ -370,15 +373,15 @@ cga_render(cga_t *cga, int line)
} else {
cols[0] = 0;
cols[1] = (cga->cgacol & 15) + 16;
for (x = 0; x < cga->crtc[1]; x++) {
if (cga->cgamode & 8)
dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) |
cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1];
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; x++) {
if (cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE)
dat = (cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000)] << 8) |
cga->vram[((cga->memaddr << 1) & 0x1fff) + ((cga->scanline & 1) * 0x2000) + 1];
else
dat = 0;
cga->ma++;
for (c = 0; c < 16; c++) {
buffer32->line[line][(x << 4) + c + 8] = cols[dat >> 15];
cga->memaddr++;
for (column = 0; column < 16; column++) {
buffer32->line[line][(x << 4) + column + 8] = cols[dat >> 15];
dat <<= 1;
}
}
@@ -388,12 +391,14 @@ cga_render(cga_t *cga, int line)
static void
cga_render_blank(cga_t *cga, int line)
{
int col = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16;
int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
if (cga->cgamode & 1)
hline(buffer32, 0, line, (cga->crtc[1] << 3) + 16, col);
int col = ((cga->cgamode & highres_graphics_flag) == highres_graphics_flag) ? 0 : (cga->cgacol & 15) + 16;
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
hline(buffer32, 0, line, (cga->crtc[CGA_CRTC_HDISP] << 3) + 16, col);
else
hline(buffer32, 0, line, (cga->crtc[1] << 4) + 16, col);
hline(buffer32, 0, line, (cga->crtc[CGA_CRTC_HDISP] << 4) + 16, col);
}
static void
@@ -401,14 +406,15 @@ cga_render_process(cga_t *cga, int line)
{
int x;
uint8_t border;
int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3) + 16;
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (cga->crtc[CGA_CRTC_HDISP] << 3) + 16;
else
x = (cga->crtc[1] << 4) + 16;
x = (cga->crtc[CGA_CRTC_HDISP] << 4) + 16;
if (cga->composite) {
border = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15);
border = ((cga->cgamode & highres_graphics_flag) == highres_graphics_flag) ? 0 : (cga->cgacol & 15);
Composite_Process(cga->cgamode, border, x >> 2, buffer32->line[line]);
} else
@@ -513,7 +519,7 @@ cga_poll(void *priv)
{
cga_t *cga = (cga_t *) priv;
int x;
int oldsc;
int scanline_old;
int oldvc;
int xs_temp;
int ys_temp;
@@ -523,9 +529,9 @@ cga_poll(void *priv)
timer_advance_u64(&cga->timer, cga->dispofftime);
cga->cgastat |= 1;
cga->linepos = 1;
oldsc = cga->sc;
if ((cga->crtc[8] & 3) == 3)
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
scanline_old = cga->scanline;
if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3)
cga->scanline = ((cga->scanline << 1) + cga->oddeven) & 7;
if (cga->cgadispon) {
if (cga->displine < cga->firstline) {
cga->firstline = cga->displine;
@@ -541,9 +547,9 @@ cga_poll(void *priv)
cga_render(cga, cga->displine);
break;
case DOUBLE_SIMPLE:
old_ma = cga->ma;
old_ma = cga->memaddr;
cga_render(cga, cga->displine << 1);
cga->ma = old_ma;
cga->memaddr = old_ma;
cga_render(cga, (cga->displine << 1) + 1);
break;
}
@@ -572,8 +578,8 @@ cga_poll(void *priv)
break;
}
cga->sc = oldsc;
if (cga->vc == cga->crtc[7] && !cga->sc)
cga->scanline = scanline_old;
if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->scanline)
cga->cgastat |= 8;
cga->displine++;
if (cga->displine >= 360)
@@ -586,41 +592,41 @@ cga_poll(void *priv)
if (!cga->vsynctime)
cga->cgastat &= ~8;
}
if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 &&
cga->sc == ((cga->crtc[11] & 31) >> 1))) {
cga->con = 0;
cga->coff = 1;
if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 &&
cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
cga->cursorvisible = 0;
}
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
cga->maback = cga->ma;
if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->scanline == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
cga->memaddr_backup = cga->memaddr;
if (cga->vadj) {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->scanline++;
cga->scanline &= 31;
cga->memaddr = cga->memaddr_backup;
cga->vadj--;
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
cga->sc = 0;
cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
cga->scanline = 0;
}
} else if (cga->sc == cga->crtc[9]) {
cga->maback = cga->ma;
cga->sc = 0;
} else if (cga->scanline == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) {
cga->memaddr_backup = cga->memaddr;
cga->scanline = 0;
oldvc = cga->vc;
cga->vc++;
cga->vc &= 127;
if (cga->vc == cga->crtc[6])
if (cga->vc == cga->crtc[CGA_CRTC_VDISP])
cga->cgadispon = 0;
if (oldvc == cga->crtc[4]) {
if (oldvc == cga->crtc[CGA_CRTC_VTOTAL]) {
cga->vc = 0;
cga->vadj = cga->crtc[5];
cga->vadj = cga->crtc[CGA_CRTC_VTOTAL_ADJUST];
if (!cga->vadj) {
cga->cgadispon = 1;
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
cga->memaddr = cga->memaddr_backup = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
}
switch (cga->crtc[10] & 0x60) {
switch (cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) {
case 0x20:
cga->cursoron = 0;
break;
@@ -633,15 +639,15 @@ cga_poll(void *priv)
}
}
if (cga->vc == cga->crtc[7]) {
if (cga->vc == cga->crtc[CGA_CRTC_VSYNC]) {
cga->cgadispon = 0;
cga->displine = 0;
cga->vsynctime = 16;
if (cga->crtc[7]) {
if (cga->cgamode & 1)
x = (cga->crtc[1] << 3) + 16;
if (cga->crtc[CGA_CRTC_VSYNC]) {
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (cga->crtc[CGA_CRTC_HDISP] << 3) + 16;
else
x = (cga->crtc[1] << 4) + 16;
x = (cga->crtc[CGA_CRTC_HDISP] << 4) + 16;
cga->lastline++;
xs_temp = x;
@@ -657,7 +663,7 @@ cga_poll(void *priv)
if (!enable_overscan)
xs_temp -= 16;
if ((cga->cgamode & 8) && ((xs_temp != xsize) ||
if ((cga->cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) ||
(ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
@@ -691,15 +697,15 @@ cga_poll(void *priv)
video_res_x = xsize;
video_res_y = ysize;
if (cga->cgamode & 1) {
if (cga->cgamode & CGA_MODE_FLAG_HIGHRES) {
video_res_x /= 8;
video_res_y /= cga->crtc[9] + 1;
video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 2)) {
} else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
video_res_x /= 16;
video_res_y /= cga->crtc[9] + 1;
video_res_y /= cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0;
} else if (!(cga->cgamode & 16)) {
} else if (!(cga->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
video_res_x /= 2;
video_bpp = 2;
} else
@@ -711,18 +717,18 @@ cga_poll(void *priv)
cga->oddeven ^= 1;
}
} else {
cga->sc++;
cga->sc &= 31;
cga->ma = cga->maback;
cga->scanline++;
cga->scanline &= 31;
cga->memaddr = cga->memaddr_backup;
}
if (cga->cgadispon)
cga->cgastat &= ~1;
if (cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 &&
cga->sc == ((cga->crtc[10] & 31) >> 1)))
cga->con = 1;
if (cga->cgadispon && (cga->cgamode & 1)) {
for (x = 0; x < (cga->crtc[1] << 1); x++)
cga->charbuffer[x] = cga->vram[((cga->ma << 1) + x) & 0x3fff];
if (cga->scanline == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 &&
cga->scanline == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1)))
cga->cursorvisible = 1;
if (cga->cgadispon && (cga->cgamode & CGA_MODE_FLAG_HIGHRES)) {
for (x = 0; x < (cga->crtc[CGA_CRTC_HDISP] << 1); x++)
cga->charbuffer[x] = cga->vram[((cga->memaddr << 1) + x) & 0x3fff];
}
}
}

View File

@@ -37,19 +37,19 @@
#include <86box/plat_unused.h>
/* Bits in the colorplus control register: */
#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */
#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */
#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */
#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */
#define COLORPLUS_PLANE_SWAP 0x40 /* Swap planes at 0000h and 4000h */
#define COLORPLUS_640x200_MODE 0x20 /* 640x200x4 mode active */
#define COLORPLUS_320x200_MODE 0x10 /* 320x200x16 mode active */
#define COLORPLUS_EITHER_MODE 0x30 /* Either mode active */
/* Bits in the CGA graphics mode register */
#define CGA_GRAPHICS_MODE 0x02 /* CGA graphics mode selected? */
#define CGA_RGB 0
#define CGA_COMPOSITE 1
#define CGA_RGB 0
#define CGA_COMPOSITE 1
#define COMPOSITE_OLD 0
#define COMPOSITE_NEW 1
#define COMPOSITE_OLD 0
#define COMPOSITE_NEW 1
// Plantronics specific registers
#define COLORPLUS_CONTROL 0x3DD
video_timings_t timing_colorplus = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
@@ -60,7 +60,7 @@ colorplus_out(uint16_t addr, uint8_t val, void *priv)
{
colorplus_t *colorplus = (colorplus_t *) priv;
if (addr == 0x3DD) {
if (addr == COLORPLUS_CONTROL) {
colorplus->control = val & 0x70;
} else {
cga_out(addr, val, &colorplus->cga);
@@ -80,7 +80,7 @@ colorplus_write(uint32_t addr, uint8_t val, void *priv)
{
colorplus_t *colorplus = (colorplus_t *) priv;
if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) {
if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) {
addr ^= 0x4000;
} else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) {
addr &= 0x3FFF;
@@ -99,7 +99,7 @@ colorplus_read(uint32_t addr, void *priv)
{
colorplus_t *colorplus = (colorplus_t *) priv;
if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) {
if ((colorplus->control & COLORPLUS_PLANE_SWAP) && (colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) {
addr ^= 0x4000;
} else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) {
addr &= 0x3FFF;
@@ -130,7 +130,7 @@ colorplus_poll(void *priv)
uint16_t dat1;
int cols[4];
int col;
int oldsc;
int scanline_old;
static const int cols16[16] = { 0x10, 0x12, 0x14, 0x16,
0x18, 0x1A, 0x1C, 0x1E,
0x11, 0x13, 0x15, 0x17,
@@ -140,7 +140,7 @@ colorplus_poll(void *priv)
/* If one of the extra modes is not selected, drop down to the CGA
* drawing code. */
if (!((colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_GRAPHICS_MODE))) {
if (!((colorplus->control & COLORPLUS_EITHER_MODE) && (colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS))) {
cga_poll(&colorplus->cga);
return;
}
@@ -149,9 +149,9 @@ colorplus_poll(void *priv)
timer_advance_u64(&colorplus->cga.timer, colorplus->cga.dispofftime);
colorplus->cga.cgastat |= 1;
colorplus->cga.linepos = 1;
oldsc = colorplus->cga.sc;
if ((colorplus->cga.crtc[8] & 3) == 3)
colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7;
scanline_old = colorplus->cga.scanline;
if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3)
colorplus->cga.scanline = ((colorplus->cga.scanline << 1) + colorplus->cga.oddeven) & 7;
if (colorplus->cga.cgadispon) {
if (colorplus->cga.displine < colorplus->cga.firstline) {
colorplus->cga.firstline = colorplus->cga.displine;
@@ -160,13 +160,13 @@ colorplus_poll(void *priv)
colorplus->cga.lastline = colorplus->cga.displine;
/* Left / right border */
for (c = 0; c < 8; c++) {
buffer32->line[colorplus->cga.displine][c] = buffer32->line[colorplus->cga.displine][c + (colorplus->cga.crtc[1] << 4) + 8] = (colorplus->cga.cgacol & 15) + 16;
buffer32->line[colorplus->cga.displine][c] = buffer32->line[colorplus->cga.displine][c + (colorplus->cga.crtc[CGA_CRTC_HDISP] << 4) + 8] = (colorplus->cga.cgacol & 15) + 16;
}
if (colorplus->control & COLORPLUS_320x200_MODE) {
for (x = 0; x < colorplus->cga.crtc[1]; x++) {
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
colorplus->cga.ma++;
for (x = 0; x < colorplus->cga.crtc[CGA_CRTC_HDISP]; x++) {
dat0 = (plane0[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000) + 1];
dat1 = (plane1[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000) + 1];
colorplus->cga.memaddr++;
for (c = 0; c < 8; c++) {
buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[colorplus->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)];
dat0 <<= 2;
@@ -176,7 +176,7 @@ colorplus_poll(void *priv)
} else if (colorplus->control & COLORPLUS_640x200_MODE) {
cols[0] = (colorplus->cga.cgacol & 15) | 16;
col = (colorplus->cga.cgacol & 16) ? 24 : 16;
if (colorplus->cga.cgamode & 4) {
if (colorplus->cga.cgamode & CGA_MODE_FLAG_BW) {
cols[1] = col | 3;
cols[2] = col | 4;
cols[3] = col | 7;
@@ -189,10 +189,10 @@ colorplus_poll(void *priv)
cols[2] = col | 4;
cols[3] = col | 6;
}
for (x = 0; x < colorplus->cga.crtc[1]; x++) {
dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1];
colorplus->cga.ma++;
for (x = 0; x < colorplus->cga.crtc[CGA_CRTC_HDISP]; x++) {
dat0 = (plane0[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000)] << 8) | plane0[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000) + 1];
dat1 = (plane1[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000)] << 8) | plane1[((colorplus->cga.memaddr << 1) & 0x1fff) + ((colorplus->cga.scanline & 1) * 0x2000) + 1];
colorplus->cga.memaddr++;
for (c = 0; c < 16; c++) {
buffer32->line[colorplus->cga.displine][(x << 4) + c + 8] = cols[(dat0 >> 15) | ((dat1 >> 15) << 1)];
dat0 <<= 1;
@@ -203,18 +203,18 @@ colorplus_poll(void *priv)
} else /* Top / bottom border */
{
cols[0] = (colorplus->cga.cgacol & 15) + 16;
hline(buffer32, 0, colorplus->cga.displine, (colorplus->cga.crtc[1] << 4) + 16, cols[0]);
hline(buffer32, 0, colorplus->cga.displine, (colorplus->cga.crtc[CGA_CRTC_HDISP] << 4) + 16, cols[0]);
}
x = (colorplus->cga.crtc[1] << 4) + 16;
x = (colorplus->cga.crtc[CGA_CRTC_HDISP] << 4) + 16;
if (colorplus->cga.composite)
Composite_Process(colorplus->cga.cgamode, 0, x >> 2, buffer32->line[colorplus->cga.displine]);
else
video_process_8(x, colorplus->cga.displine);
colorplus->cga.sc = oldsc;
if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc)
colorplus->cga.scanline = scanline_old;
if (colorplus->cga.vc == colorplus->cga.crtc[CGA_CRTC_VSYNC] && !colorplus->cga.scanline)
colorplus->cga.cgastat |= 8;
colorplus->cga.displine++;
if (colorplus->cga.displine >= 360)
@@ -227,54 +227,54 @@ colorplus_poll(void *priv)
if (!colorplus->cga.vsynctime)
colorplus->cga.cgastat &= ~8;
}
if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1))) {
colorplus->cga.con = 0;
colorplus->cga.coff = 1;
if (colorplus->cga.scanline == (colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31)
|| ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.scanline == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
colorplus->cga.cursorvisible = 0;
}
if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1))
colorplus->cga.maback = colorplus->cga.ma;
if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.scanline == (colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
colorplus->cga.memaddr_backup = colorplus->cga.memaddr;
if (colorplus->cga.vadj) {
colorplus->cga.sc++;
colorplus->cga.sc &= 31;
colorplus->cga.ma = colorplus->cga.maback;
colorplus->cga.scanline++;
colorplus->cga.scanline &= 31;
colorplus->cga.memaddr = colorplus->cga.memaddr_backup;
colorplus->cga.vadj--;
if (!colorplus->cga.vadj) {
colorplus->cga.cgadispon = 1;
colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
colorplus->cga.sc = 0;
colorplus->cga.memaddr = colorplus->cga.memaddr_backup = (colorplus->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (colorplus->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
colorplus->cga.scanline = 0;
}
} else if (colorplus->cga.sc == colorplus->cga.crtc[9]) {
colorplus->cga.maback = colorplus->cga.ma;
colorplus->cga.sc = 0;
} else if (colorplus->cga.scanline == colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) {
colorplus->cga.memaddr_backup = colorplus->cga.memaddr;
colorplus->cga.scanline = 0;
oldvc = colorplus->cga.vc;
colorplus->cga.vc++;
colorplus->cga.vc &= 127;
if (colorplus->cga.vc == colorplus->cga.crtc[6])
if (colorplus->cga.vc == colorplus->cga.crtc[CGA_CRTC_VDISP])
colorplus->cga.cgadispon = 0;
if (oldvc == colorplus->cga.crtc[4]) {
if (oldvc == colorplus->cga.crtc[CGA_CRTC_VTOTAL]) {
colorplus->cga.vc = 0;
colorplus->cga.vadj = colorplus->cga.crtc[5];
colorplus->cga.vadj = colorplus->cga.crtc[CGA_CRTC_VTOTAL_ADJUST];
if (!colorplus->cga.vadj)
colorplus->cga.cgadispon = 1;
if (!colorplus->cga.vadj)
colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff;
if ((colorplus->cga.crtc[10] & 0x60) == 0x20)
colorplus->cga.memaddr = colorplus->cga.memaddr_backup = (colorplus->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (colorplus->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
if ((colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20)
colorplus->cga.cursoron = 0;
else
colorplus->cga.cursoron = colorplus->cga.cgablink & 8;
}
if (colorplus->cga.vc == colorplus->cga.crtc[7]) {
if (colorplus->cga.vc == colorplus->cga.crtc[CGA_CRTC_VSYNC]) {
colorplus->cga.cgadispon = 0;
colorplus->cga.displine = 0;
colorplus->cga.vsynctime = 16;
if (colorplus->cga.crtc[7]) {
if (colorplus->cga.cgamode & 1)
x = (colorplus->cga.crtc[1] << 3) + 16;
if (colorplus->cga.crtc[CGA_CRTC_VSYNC]) {
if (colorplus->cga.cgamode & CGA_MODE_FLAG_HIGHRES)
x = (colorplus->cga.crtc[CGA_CRTC_HDISP] << 3) + 16;
else
x = (colorplus->cga.crtc[1] << 4) + 16;
x = (colorplus->cga.crtc[CGA_CRTC_HDISP] << 4) + 16;
colorplus->cga.lastline++;
if (x != xsize || (colorplus->cga.lastline - colorplus->cga.firstline) != ysize) {
xsize = x;
@@ -291,15 +291,15 @@ colorplus_poll(void *priv)
video_res_x = xsize - 16;
video_res_y = ysize;
if (colorplus->cga.cgamode & 1) {
if (colorplus->cga.cgamode & CGA_MODE_FLAG_HIGHRES) {
video_res_x /= 8;
video_res_y /= colorplus->cga.crtc[9] + 1;
video_res_y /= colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0;
} else if (!(colorplus->cga.cgamode & 2)) {
} else if (!(colorplus->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) {
video_res_x /= 16;
video_res_y /= colorplus->cga.crtc[9] + 1;
video_res_y /= colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
video_bpp = 0;
} else if (!(colorplus->cga.cgamode & 16)) {
} else if (!(colorplus->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)) {
video_res_x /= 2;
video_bpp = 2;
} else {
@@ -312,17 +312,17 @@ colorplus_poll(void *priv)
colorplus->cga.oddeven ^= 1;
}
} else {
colorplus->cga.sc++;
colorplus->cga.sc &= 31;
colorplus->cga.ma = colorplus->cga.maback;
colorplus->cga.scanline++;
colorplus->cga.scanline &= 31;
colorplus->cga.memaddr = colorplus->cga.memaddr_backup;
}
if (colorplus->cga.cgadispon)
colorplus->cga.cgastat &= ~1;
if (colorplus->cga.sc == (colorplus->cga.crtc[10] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[10] & 31) >> 1)))
colorplus->cga.con = 1;
if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1)) {
for (x = 0; x < (colorplus->cga.crtc[1] << 1); x++)
colorplus->cga.charbuffer[x] = colorplus->cga.vram[((colorplus->cga.ma << 1) + x) & 0x3fff];
if (colorplus->cga.scanline == (colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.scanline == ((colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1)))
colorplus->cga.cursorvisible = 1;
if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) {
for (x = 0; x < (colorplus->cga.crtc[CGA_CRTC_HDISP] << 1); x++)
colorplus->cga.charbuffer[x] = colorplus->cga.vram[((colorplus->cga.memaddr << 1) + x) & 0x3fff];
}
}
}

View File

@@ -135,7 +135,7 @@ update_cga16_color(uint8_t cgamode)
int left = (x >> 6) & 15;
int rc = right;
int lc = left;
if ((cgamode & 4) != 0) {
if ((cgamode & CGA_MODE_FLAG_BW) != 0) {
rc = (right & 8) | ((right & 7) != 0 ? 7 : 0);
lc = (left & 8) | ((left & 7) != 0 ? 7 : 0);
}
@@ -240,7 +240,7 @@ Composite_Process(uint8_t cgamode, uint8_t border, uint32_t blocks /*, bool doub
for (uint8_t x = 0; x < 5; ++x)
OUT(b[x & 3]);
if ((cgamode & 4) != 0) {
if ((cgamode & CGA_MODE_FLAG_BW) != 0) {
/* Decode */
i = temp + 5;
srgb = TempLine;

511
src/video/vid_cga_compaq.c Normal file
View File

@@ -0,0 +1,511 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the Compaq CGA graphics cards.
*
*
*
* Authors: John Elliott, <jce@seasip.info>
* Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2019 John Elliott.
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/video.h>
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#define CGA_RGB 0
#define CGA_COMPOSITE 1
static uint32_t vflags;
static uint8_t mdaattr[256][2][2];
#ifdef ENABLE_COMPAQ_CGA_LOG
int compaq_cga_do_log = ENABLE_COMPAQ_CGA_LOG;
static void
compaq_cga_log(const char *fmt, ...)
{
va_list ap;
if (compaq_cga_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define compaq_cga_log(fmt, ...)
#endif
static void
compaq_cga_recalctimings(cga_t *dev)
{
double _dispontime;
double _dispofftime;
double disptime;
disptime = dev->crtc[CGA_CRTC_HTOTAL] + 1;
_dispontime = dev->crtc[CGA_CRTC_HDISP];
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
dev->dispontime = (uint64_t) (_dispontime);
dev->dispofftime = (uint64_t) (_dispofftime);
}
static void
compaq_cga_poll(void *priv)
{
cga_t *dev = (cga_t *) priv;
uint16_t cursoraddr = (dev->crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (dev->crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
int xs_temp;
int ys_temp;
int oldvc;
uint8_t chr;
uint8_t attr;
uint8_t border;
uint8_t cols[4];
int scanline_old;
int underline = 0;
int blink = 0;
int32_t highres_graphics_flag = (CGA_MODE_FLAG_HIGHRES_GRAPHICS | CGA_MODE_FLAG_GRAPHICS);
/* If in graphics mode or character height is not 13, behave as CGA */
if ((dev->cgamode & highres_graphics_flag) || (dev->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] != 13)) {
overscan_x = overscan_y = 16;
cga_poll(dev);
return;
} else
overscan_x = overscan_y = 0;
/* We are in Compaq 350-line CGA territory */
if (!dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->cgastat |= 1;
dev->linepos = 1;
scanline_old = dev->scanline;
if ((dev->crtc[CGA_CRTC_INTERLACE] & 3) == 3)
dev->scanline = ((dev->scanline << 1) + dev->oddeven) & 7;
if (dev->cgadispon) {
if (dev->displine < dev->firstline) {
dev->firstline = dev->displine;
video_wait_for_buffer();
compaq_cga_log("Firstline %i\n", dev->firstline);
}
dev->lastline = dev->displine;
cols[0] = (dev->cgacol & 15) + 16;
for (c = 0; c < 8; c++) {
buffer32->line[dev->displine][c] = cols[0];
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES)
buffer32->line[dev->displine][c + (dev->crtc[CGA_CRTC_HDISP] << 3) + 8] = cols[0];
else
buffer32->line[dev->displine][c + (dev->crtc[CGA_CRTC_HDISP] << 4) + 8] = cols[0];
}
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES) {
for (x = 0; x < dev->crtc[CGA_CRTC_HDISP]; x++) {
chr = dev->charbuffer[x << 1];
attr = dev->charbuffer[(x << 1) + 1];
drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron);
if (vflags) {
underline = 0;
blink = ((dev->cgablink & 8) && (dev->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
}
if (vflags && (dev->cgamode & 0x80)) {
cols[0] = mdaattr[attr][blink][0];
cols[1] = mdaattr[attr][blink][1];
if ((dev->scanline == 12) && ((attr & 7) == 1))
underline = 1;
} else if (dev->cgamode & CGA_MODE_FLAG_BLINK) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if (vflags) {
if (blink)
cols[1] = cols[0];
} else {
if ((dev->cgablink & 8) && (attr & 0x80) && !dev->drawcursor)
cols[1] = cols[0];
}
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
if (vflags && underline) {
for (c = 0; c < 8; c++)
buffer32->line[dev->displine][(x << 3) + c + 8] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[dev->displine][(x << 3) + c + 8] =
cols[(fontdatm[chr + dev->fontbase][dev->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[dev->displine][(x << 3) + c + 8] =
cols[(fontdatm[chr + dev->fontbase][dev->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0];
}
dev->memaddr++;
}
} else {
for (x = 0; x < dev->crtc[CGA_CRTC_HDISP]; x++) {
chr = dev->vram[(dev->memaddr << 1) & 0x3fff];
attr = dev->vram[((dev->memaddr << 1) + 1) & 0x3fff];
drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron);
if (vflags) {
underline = 0;
blink = ((dev->cgablink & 8) && (dev->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
}
if (vflags && (dev->cgamode & 0x80)) {
cols[0] = mdaattr[attr][blink][0];
cols[1] = mdaattr[attr][blink][1];
if (dev->scanline == 12 && (attr & 7) == 1)
underline = 1;
} else if (dev->cgamode & CGA_MODE_FLAG_BLINK) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if (vflags) {
if (blink)
cols[1] = cols[0];
} else {
if ((dev->cgablink & 8) && (attr & 0x80) && !dev->drawcursor)
cols[1] = cols[0];
}
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
dev->memaddr++;
if (vflags && underline) {
for (c = 0; c < 8; c++)
buffer32->line[dev->displine][(x << 4) + (c << 1) + 8] =
buffer32->line[dev->displine][(x << 4) + (c << 1) + 9] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[dev->displine][(x << 4) + (c << 1) + 8] =
buffer32->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] =
cols[(fontdatm[chr + dev->fontbase][dev->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[dev->displine][(x << 4) + (c << 1) + 8] =
buffer32->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] =
cols[(fontdatm[chr + dev->fontbase][dev->scanline & 15] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
} else {
cols[0] = (dev->cgacol & 15) + 16;
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES)
hline(buffer32, 0, dev->displine, (dev->crtc[CGA_CRTC_HDISP] << 3) + 16, cols[0]);
else
hline(buffer32, 0, dev->displine, (dev->crtc[CGA_CRTC_HDISP] << 4) + 16, cols[0]);
}
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (dev->crtc[CGA_CRTC_HDISP] << 3) + 16;
else
x = (dev->crtc[CGA_CRTC_HDISP] << 4) + 16;
if (dev->composite) {
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)
border = 0x00;
else
border = dev->cgacol & 0x0f;
if (vflags)
Composite_Process(dev->cgamode & 0x7f, border, x >> 2, buffer32->line[dev->displine]);
else
Composite_Process(dev->cgamode, border, x >> 2, buffer32->line[dev->displine]);
} else
video_process_8(x, dev->displine);
dev->scanline = scanline_old;
if (dev->vc == dev->crtc[CGA_CRTC_VSYNC] && !dev->scanline)
dev->cgastat |= 8;
dev->displine++;
if (dev->displine >= 500)
dev->displine = 0;
} else {
timer_advance_u64(&dev->timer, dev->dispontime);
dev->linepos = 0;
if (dev->vsynctime) {
dev->vsynctime--;
if (!dev->vsynctime)
dev->cgastat &= ~8;
}
if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) {
dev->cursorvisible = 0;
}
if ((dev->crtc[8] & 3) == 3 && dev->scanline == (dev->crtc[9] >> 1))
dev->memaddr_backup = dev->memaddr;
if (dev->vadj) {
dev->scanline++;
dev->scanline &= 31;
dev->memaddr = dev->memaddr_backup;
dev->vadj--;
if (!dev->vadj) {
dev->cgadispon = 1;
dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->scanline = 0;
}
} else if (dev->scanline == dev->crtc[9]) {
dev->memaddr_backup = dev->memaddr;
dev->scanline = 0;
oldvc = dev->vc;
dev->vc++;
dev->vc &= 127;
if (dev->vc == dev->crtc[6])
dev->cgadispon = 0;
if (oldvc == dev->crtc[4]) {
dev->vc = 0;
dev->vadj = dev->crtc[5];
if (!dev->vadj)
dev->cgadispon = 1;
if (!dev->vadj)
dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
if ((dev->crtc[10] & 0x60) == 0x20)
dev->cursoron = 0;
else
dev->cursoron = dev->cgablink & 8;
}
if (dev->vc == dev->crtc[7]) {
dev->cgadispon = 0;
dev->displine = 0;
dev->vsynctime = 16;
if (dev->crtc[7]) {
compaq_cga_log("Lastline %i Firstline %i %i\n", dev->lastline,
dev->firstline, dev->lastline - dev->firstline);
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES)
x = (dev->crtc[CGA_CRTC_HDISP] << 3) + 16;
else
x = (dev->crtc[CGA_CRTC_HDISP] << 4) + 16;
dev->lastline++;
xs_temp = x;
ys_temp = (dev->lastline - dev->firstline);
if ((xs_temp > 0) && (ys_temp > 0)) {
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= 16;
if ((dev->cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
if (enable_overscan)
video_blit_memtoscreen(0, dev->firstline - 8, xsize, (dev->lastline - dev->firstline) + 16);
else
video_blit_memtoscreen(8, dev->firstline, xsize, dev->lastline - dev->firstline);
}
frames++;
video_res_x = xsize;
if (enable_overscan)
xsize -= 16;
video_res_y = ysize;
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES) {
video_res_x /= 8;
video_res_y /= dev->crtc[9] + 1;
video_bpp = 0;
} else if (!(dev->cgamode & 2)) {
video_res_x /= 16;
video_res_y /= dev->crtc[9] + 1;
video_bpp = 0;
} else if (!(dev->cgamode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else
video_bpp = 1;
}
dev->firstline = 1000;
dev->lastline = 0;
dev->cgablink++;
dev->oddeven ^= 1;
}
} else {
dev->scanline++;
dev->scanline &= 31;
dev->memaddr = dev->memaddr_backup;
}
if (dev->cgadispon)
dev->cgastat &= ~1;
if (dev->scanline == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[10] & 31) >> 1)))
dev->cursorvisible = 1;
if (dev->cgadispon && (dev->cgamode & CGA_MODE_FLAG_HIGHRES)) {
for (x = 0; x < (dev->crtc[CGA_CRTC_HDISP] << 1); x++)
dev->charbuffer[x] = dev->vram[((dev->memaddr << 1) + x) & 0x3fff];
}
}
}
static void *
compaq_cga_init(const device_t *info)
{
int display_type;
cga_t *dev = calloc(1, sizeof(cga_t));
display_type = device_get_config_int("display_type");
dev->composite = (display_type != CGA_RGB);
dev->revision = device_get_config_int("composite_type");
dev->snow_enabled = device_get_config_int("snow_enabled");
dev->vram = malloc(0x4000);
cga_comp_init(dev->revision);
timer_add(&dev->timer, compaq_cga_poll, dev, 1);
mem_mapping_add(&dev->mapping, 0xb8000, 0x08000,
cga_read, NULL, NULL,
cga_write, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL, dev);
io_sethandler(0x03d0, 0x0010,
cga_in, NULL, NULL,
cga_out, NULL, NULL,
dev);
if (info->local) {
for (uint16_t c = 0; c < 256; c++) {
mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16;
if (c & 8)
mdaattr[c][0][1] = 15 + 16;
else
mdaattr[c][0][1] = 7 + 16;
}
mdaattr[0x70][0][1] = 16;
mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15;
mdaattr[0xF0][0][1] = 16;
mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15;
mdaattr[0x78][0][1] = 16 + 7;
mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15;
mdaattr[0xF8][0][1] = 16 + 7;
mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15;
mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16;
mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16;
mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16;
mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16;
}
vflags = info->local;
overscan_x = overscan_y = 16;
dev->rgb_type = device_get_config_int("rgb_type");
cga_palette = (dev->rgb_type << 1);
cgapal_rebuild();
dev->crtc[9] = 13;
return dev;
}
static void
compaq_cga_close(void *priv)
{
cga_t *dev = (cga_t *) priv;
free(dev->vram);
free(dev);
}
static void
compaq_cga_speed_changed(void *priv)
{
cga_t *dev = (cga_t *) priv;
if (dev->crtc[9] == 13) /* Character height */
compaq_cga_recalctimings(dev);
else
cga_recalctimings(dev);
}
extern const device_config_t cga_config[];
const device_t compaq_cga_device = {
.name = "Compaq CGA",
.internal_name = "compaq_cga",
.flags = DEVICE_ISA,
.local = 0,
.init = compaq_cga_init,
.close = compaq_cga_close,
.reset = NULL,
.available = NULL,
.speed_changed = compaq_cga_speed_changed,
.force_redraw = NULL,
.config = cga_config
};
const device_t compaq_cga_2_device = {
.name = "Compaq CGA 2",
.internal_name = "compaq_cga_2",
.flags = DEVICE_ISA,
.local = 1,
.init = compaq_cga_init,
.close = compaq_cga_close,
.reset = NULL,
.available = NULL,
.speed_changed = compaq_cga_speed_changed,
.force_redraw = NULL,
.config = cga_config
};

View File

@@ -0,0 +1,843 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the plasma displays on early Compaq Portables and laptops.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2025 starfrost
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/video.h>
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#include <86box/plat_unused.h>
static video_timings_t timing_compaq_plasma = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
#define CGA_RGB 0
#define CGA_COMPOSITE 1
/*Very rough estimate*/
#define VID_CLOCK (double) (651 * 416 * 60)
/* Mapping of attributes to colours */
static uint32_t amber;
static uint32_t black;
static uint32_t blinkcols[256][2];
static uint32_t normcols[256][2];
/* Video options set by the motherboard; they will be picked up by the card
* on the next poll.
*
* Bit 3: Disable built-in video (for add-on card)
* Bit 2: Thin font
* Bits 0,1: Font set (not currently implemented)
*/
static int8_t cpq_st_display_internal = -1;
static uint8_t mdaattr[256][2][2];
static void
compaq_plasma_display_set(uint8_t internal)
{
cpq_st_display_internal = internal;
}
typedef struct compaq_plasma_t {
cga_t cga;
mem_mapping_t font_ram_mapping;
uint8_t *font_ram;
uint8_t port_13c6;
uint8_t port_23c6;
uint8_t port_27c6;
uint8_t internal_monitor;
} compaq_plasma_t;
static void compaq_plasma_recalcattrs(compaq_plasma_t *self);
static void
compaq_plasma_recalctimings(compaq_plasma_t *self)
{
double _dispontime;
double _dispofftime;
double disptime;
if (!self->internal_monitor && !(self->port_23c6 & 0x01)) {
cga_recalctimings(&self->cga);
return;
}
disptime = 651;
_dispontime = 640;
_dispofftime = disptime - _dispontime;
self->cga.dispontime = (uint64_t) (_dispontime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32));
self->cga.dispofftime = (uint64_t) (_dispofftime * (cpuclock / VID_CLOCK) * (double) (1ULL << 32));
}
static void
compaq_plasma_waitstates(UNUSED(void *priv))
{
int ws_array[16] = { 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8 };
int ws;
ws = ws_array[cycles & 0xf];
sub_cycles(ws);
}
static void
compaq_plasma_write(uint32_t addr, uint8_t val, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
if (self->port_23c6 & 0x08)
self->font_ram[addr & 0x1fff] = val;
else
self->cga.vram[addr & 0x7fff] = val;
compaq_plasma_waitstates(&self->cga);
}
static uint8_t
compaq_plasma_read(uint32_t addr, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t ret;
compaq_plasma_waitstates(&self->cga);
if (self->port_23c6 & 0x08)
ret = (self->font_ram[addr & 0x1fff]);
else
ret = (self->cga.vram[addr & 0x7fff]);
return ret;
}
static void
compaq_plasma_out(uint16_t addr, uint8_t val, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
switch (addr) {
/* Emulated CRTC, register select */
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
cga_out(addr, val, &self->cga);
break;
/* Emulated CRTC, value */
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
cga_out(addr, val, &self->cga);
compaq_plasma_recalctimings(self);
break;
case 0x3d8:
case 0x3d9:
cga_out(addr, val, &self->cga);
break;
case 0x13c6:
self->port_13c6 = val;
compaq_plasma_display_set((self->port_13c6 & 0x08) ? 1 : 0);
/*
For bits 2-0, John gives 0 = CGA, 1 = EGA, 3 = MDA;
Another source (Ralf Brown?) gives 4 = CGA, 5 = EGA, 7 = MDA;
This leads me to believe bit 2 is not relevant to the mode.
*/
if ((val & 0x07) == 0x03)
mem_mapping_set_addr(&self->cga.mapping, 0xb0000, 0x08000);
else
mem_mapping_set_addr(&self->cga.mapping, 0xb8000, 0x08000);
break;
case 0x23c6:
self->port_23c6 = val;
break;
case 0x27c6:
self->port_27c6 = val;
break;
default:
break;
}
}
static uint8_t
compaq_plasma_in(uint16_t addr, void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x3d4:
case 0x3da:
case 0x3db:
case 0x3dc:
ret = cga_in(addr, &self->cga);
break;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
ret = cga_in(addr, &self->cga);
break;
case 0x3d8:
ret = self->cga.cgamode;
break;
case 0x13c6:
ret = self->port_13c6;
break;
case 0x17c6:
ret = 0xe6;
break;
case 0x1bc6:
ret = 0x40;
break;
case 0x23c6:
ret = self->port_23c6;
break;
case 0x27c6:
ret = self->port_27c6 & 0x3f;
break;
default:
break;
}
return ret;
}
static void
compaq_plasma_poll(void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
uint8_t chr;
uint8_t attr;
uint8_t scanline;
uint16_t memaddr = (self->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
uint16_t cursoraddr = (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff;
uint16_t addr;
int drawcursor;
int cursorline;
int blink = 0;
int underline = 0;
int cursorvisible = 0;
int cursorinvisible = 0;
int c;
int x;
uint32_t ink = 0;
uint32_t fg = (self->cga.cgacol & 0x0f) ? amber : black;
uint32_t bg = black;
uint32_t black_half = black;
uint32_t amber_half = amber;
uint32_t cols[2];
uint8_t dat;
uint8_t pattern;
uint32_t ink0 = 0;
uint32_t ink1 = 0;
/* Switch between internal plasma and external CRT display. */
if ((cpq_st_display_internal != -1) && (cpq_st_display_internal != self->internal_monitor)) {
self->internal_monitor = cpq_st_display_internal;
compaq_plasma_recalctimings(self);
}
/* graphic mode and not mode 40h */
if (!self->internal_monitor && !(self->port_23c6 & 0x01)) {
/* standard cga mode */
cga_poll(&self->cga);
return;
} else {
/* mode 40h or text mode */
if (!self->cga.linepos) {
timer_advance_u64(&self->cga.timer, self->cga.dispofftime);
self->cga.cgastat |= 1;
self->cga.linepos = 1;
if (self->cga.cgadispon) {
if (self->cga.displine == 0)
video_wait_for_buffer();
/* 80-col */
if (self->cga.cgamode & 0x01) {
scanline = self->cga.displine & 0x0f;
addr = ((memaddr & ~1) + (self->cga.displine >> 4) * 80) << 1;
memaddr += (self->cga.displine >> 4) * 80;
if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20)
cursorline = 0;
else {
if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) > 0x07)
cursorvisible = (self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) + 1;
else
cursorvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1);
if ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) > 0x07)
cursorinvisible = (self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) + 2;
else
cursorinvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1);
cursorline = (cursorvisible <= scanline) && (cursorinvisible >= scanline);
}
/* for each text column */
for (x = 0; x < 80; x++) {
/* video output enabled */
if (self->cga.cgamode & 0x08) {
/* character */
chr = self->cga.vram[(addr + (x << 1)) & 0x7fff];
/* text attributes */
attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff];
} else {
chr = 0x00;
attr = 0x00;
}
uint8_t hi_bit = attr & 0x08;
/* check if cursor has to be drawn */
drawcursor = ((memaddr == cursoraddr) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10));
/* check if character underline mode should be set */
underline = ((attr & 0x07) == 0x01);
underline = underline || (((self->port_23c6 >> 5) == 1) && hi_bit);
if (underline) {
/* set forecolor to white */
attr = attr | 0x7;
}
blink = 0;
/* set foreground */
cols[1] = blinkcols[attr][1];
/* blink active */
if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) {
/* set blinking */
cols[1] = cols[0];
blink = 1;
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character address */
uint16_t chr_addr = ((chr * 16) + scanline) & 0x0fff;
if (((self->port_23c6 >> 5) == 3) && hi_bit)
chr_addr |= 0x1000;
/* character underline active and 7th row of pixels in character height being drawn */
if (underline) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
if (hi_bit) {
if ((self->port_23c6 >> 5) == 4) {
uint8_t b = (cols[1] & 0xff) >> 1;
uint8_t g = ((cols[1] >> 8) & 0xff) >> 1;
uint8_t r = ((cols[1] >> 16) & 0xff) >> 1;
cols[1] = b | (g << 8) | (r << 16);
b = (cols[0] & 0xff) >> 1;
g = ((cols[0] >> 8) & 0xff) >> 1;
r = ((cols[0] >> 16) & 0xff) >> 1;
cols[0] = b | (g << 8) | (r << 16);
if (drawcursor) {
black_half = black;
amber_half = amber;
uint8_t bB = (black & 0xff) >> 1;
uint8_t gB = ((black >> 8) & 0xff) >> 1;
uint8_t rB = ((black >> 16) & 0xff) >> 1;
black_half = bB | (gB << 8) | (rB << 16);
uint8_t bA = (amber & 0xff) >> 1;
uint8_t gA = ((amber >> 8) & 0xff) >> 1;
uint8_t rA = ((amber >> 16) & 0xff) >> 1;
amber_half = bA | (gA << 8) | (rA << 16);
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
} else if ((self->port_23c6 >> 5) == 2) {
if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1];
}
}
}
memaddr++;
}
}
/* 40-col */
else if (!(self->cga.cgamode & 0x02)) {
scanline = self->cga.displine & 0x0f;
addr = ((memaddr & ~1) + (self->cga.displine >> 4) * 40) << 1;
memaddr += (self->cga.displine >> 4) * 40;
if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20)
cursorline = 0;
else {
if ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) > 0x07)
cursorvisible = (self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) + 1;
else
cursorvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1);
if ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) > 0x07)
cursorinvisible = (self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) + 2;
else
cursorinvisible = ((self->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0f) << 1);
cursorline = (cursorvisible <= scanline) && (cursorinvisible >= scanline);
}
for (x = 0; x < 40; x++) {
/* video output enabled */
if (self->cga.cgamode & 0x08) {
/* character */
chr = self->cga.vram[(addr + (x << 1)) & 0x7fff];
/* text attributes */
attr = self->cga.vram[(addr + ((x << 1) + 1)) & 0x7fff];
} else {
chr = 0x00;
attr = 0x00;
}
uint8_t hi_bit = attr & 0x08;
/* check if cursor has to be drawn */
drawcursor = ((memaddr == cursoraddr) && cursorline && (self->cga.cgamode & 0x08) && (self->cga.cgablink & 0x10));
/* check if character underline mode should be set */
underline = ((attr & 0x07) == 0x01);
underline = underline || (((self->port_23c6 >> 5) == 1) && hi_bit);
if (underline) {
/* set forecolor to white */
attr = attr | 0x7;
}
blink = 0;
/* set foreground */
cols[1] = blinkcols[attr][1];
/* blink active */
if (self->cga.cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = blinkcols[attr][0];
/* attribute 7 active and not cursor */
if ((self->cga.cgablink & 0x08) && (attr & 0x80) && !drawcursor) {
/* set blinking */
cols[1] = cols[0];
blink = 1;
}
} else {
/* Set intensity bit */
cols[1] = normcols[attr][1];
cols[0] = normcols[attr][0];
}
/* character address */
uint16_t chr_addr = ((chr * 16) + scanline) & 0x0fff;
if (((self->port_23c6 >> 5) == 3) && hi_bit)
chr_addr |= 0x1000;
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (scanline == 7)) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
if (hi_bit) {
if ((self->port_23c6 >> 5) == 4) {
uint8_t b = (cols[1] & 0xff) >> 1;
uint8_t g = ((cols[1] >> 8) & 0xff) >> 1;
uint8_t r = ((cols[1] >> 16) & 0xff) >> 1;
cols[1] = b | (g << 8) | (r << 16);
b = (cols[0] & 0xff) >> 1;
g = ((cols[0] >> 8) & 0xff) >> 1;
r = ((cols[0] >> 16) & 0xff) >> 1;
cols[0] = b | (g << 8) | (r << 16);
if (drawcursor) {
black_half = black;
amber_half = amber;
uint8_t bB = (black & 0xff) >> 1;
uint8_t gB = ((black >> 8) & 0xff) >> 1;
uint8_t rB = ((black >> 16) & 0xff) >> 1;
black_half = bB | (gB << 8) | (rB << 16);
uint8_t bA = (amber & 0xff) >> 1;
uint8_t gA = ((amber >> 8) & 0xff) >> 1;
uint8_t rA = ((amber >> 16) & 0xff) >> 1;
amber_half = bA | (gA << 8) | (rA << 16);
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber_half ^ black_half);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 1 : 0];
}
} else if ((self->port_23c6 >> 5) == 2) {
if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1] ^ (amber ^ black);
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1)] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1] = cols[(self->font_ram[chr_addr] & (1 << (c ^ 7))) ? 0 : 1];
}
}
}
memaddr++;
}
} else {
if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) {
/* 640x400 mode */
if (self->port_23c6 & 0x01) /* 640*400 */ {
addr = ((self->cga.displine) & 1) * 0x2000 + ((self->cga.displine >> 1) & 1) * 0x4000 + (self->cga.displine >> 2) * 80 + ((memaddr & ~1) << 1);
} else {
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((memaddr & ~1) << 1);
}
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7fff];
addr++;
for (uint8_t c = 0; c < 8; c++) {
ink = (dat & 0x80) ? fg : bg;
if (!(self->cga.cgamode & 0x08))
ink = black;
buffer32->line[self->cga.displine][(x << 3) + c] = ink;
dat <<= 1;
}
}
} else {
addr = ((self->cga.displine >> 1) & 1) * 0x2000 + (self->cga.displine >> 2) * 80 + ((memaddr & ~1) << 1);
for (uint8_t x = 0; x < 80; x++) {
dat = self->cga.vram[addr & 0x7fff];
addr++;
for (uint8_t c = 0; c < 4; c++) {
pattern = (dat & 0xC0) >> 6;
if (!(self->cga.cgamode & 0x08))
pattern = 0;
switch (pattern & 3) {
case 0:
ink0 = ink1 = black;
break;
case 1:
if (self->cga.displine & 0x01) {
ink0 = black;
ink1 = black;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 2:
if (self->cga.displine & 0x01) {
ink0 = black;
ink1 = amber;
} else {
ink0 = amber;
ink1 = black;
}
break;
case 3:
ink0 = ink1 = amber;
break;
default:
break;
}
buffer32->line[self->cga.displine][(x << 3) + (c << 1)] = ink0;
buffer32->line[self->cga.displine][(x << 3) + (c << 1) + 1] = ink1;
dat <<= 2;
}
}
}
}
}
self->cga.displine++;
/* Hardcode a fixed refresh rate and VSYNC timing */
if (self->cga.displine == 400) { /* Start of VSYNC */
self->cga.cgastat |= 8;
self->cga.cgadispon = 0;
}
if (self->cga.displine == 416) { /* End of VSYNC */
self->cga.displine = 0;
self->cga.cgastat &= ~8;
self->cga.cgadispon = 1;
}
} else {
timer_advance_u64(&self->cga.timer, self->cga.dispontime);
if (self->cga.cgadispon)
self->cga.cgastat &= ~1;
self->cga.linepos = 0;
if (self->cga.displine == 400) {
xsize = 640;
ysize = 400;
if ((self->cga.cgamode & 0x08) || video_force_resize_get()) {
set_screen_size(xsize, ysize);
if (video_force_resize_get())
video_force_resize_set(0);
}
/* Plasma specific */
video_blit_memtoscreen(0, 0, xsize, ysize);
frames++;
/* Fixed 640x400 resolution */
video_res_x = 640;
video_res_y = 400;
if (self->cga.cgamode & 0x02) {
if (self->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)
video_bpp = 1;
else
video_bpp = 2;
} else
video_bpp = 0;
self->cga.cgablink++;
}
}
}
}
static void
compaq_plasma_mdaattr_rebuild(void)
{
for (uint16_t c = 0; c < 256; c++) {
mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16;
if (c & 8)
mdaattr[c][0][1] = 15 + 16;
else
mdaattr[c][0][1] = 7 + 16;
}
mdaattr[0x70][0][1] = 16;
mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15;
mdaattr[0xF0][0][1] = 16;
mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15;
mdaattr[0x78][0][1] = 16 + 7;
mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15;
mdaattr[0xF8][0][1] = 16 + 7;
mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15;
mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16;
mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16;
mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16;
mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16;
}
static void
compaq_plasma_recalcattrs(compaq_plasma_t *self)
{
int n;
/* val behaves as follows:
* Bit 0: Attributes 01-06, 08-0E are inverse video
* Bit 1: Attributes 01-06, 08-0E are bold
* Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF
* are inverse video
* Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF
* are bold */
/* Set up colours */
amber = makecol(0xff, 0x7d, 0x00);
black = makecol(0x64, 0x19, 0x00);
/* Initialize the attribute mapping. Start by defaulting everything
* to black on amber, and with bold set by bit 3 */
for (n = 0; n < 256; n++) {
blinkcols[n][0] = normcols[n][0] = amber;
blinkcols[n][1] = normcols[n][1] = black;
}
/* Colours 0x11-0xFF are controlled by bits 2 and 3 of the
* passed value. Exclude x0 and x8, which are always black on
* amber. */
for (n = 0x11; n <= 0xFF; n++) {
if ((n & 7) == 0)
continue;
blinkcols[n][0] = normcols[n][0] = black;
blinkcols[n][1] = normcols[n][1] = amber;
}
/* Set up the 01-0E range, controlled by bits 0 and 1 of the
* passed value. When blinking is enabled this also affects 81-8E. */
for (n = 0x01; n <= 0x0E; n++) {
if (n == 7)
continue;
blinkcols[n][0] = normcols[n][0] = black;
blinkcols[n][1] = normcols[n][1] = amber;
blinkcols[n + 128][0] = black;
blinkcols[n + 128][1] = amber;
}
/* Colours 07 and 0F are always amber on black. If blinking is
* enabled so are 87 and 8F. */
for (n = 0x07; n <= 0x0F; n += 8) {
blinkcols[n][0] = normcols[n][0] = black;
blinkcols[n][1] = normcols[n][1] = amber;
blinkcols[n + 128][0] = black;
blinkcols[n + 128][1] = amber;
}
/* When not blinking, colours 81-8F are always amber on black. */
for (n = 0x81; n <= 0x8F; n++) {
normcols[n][0] = black;
normcols[n][1] = amber;
}
/* Finally do the ones which are solid black. These differ between
* the normal and blinking mappings */
for (n = 0; n <= 0xFF; n += 0x11)
normcols[n][0] = normcols[n][1] = black;
/* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */
for (n = 0; n <= 0x77; n += 0x11) {
blinkcols[n][0] = blinkcols[n][1] = black;
blinkcols[n + 128][0] = blinkcols[n + 128][1] = black;
}
}
static void *
compaq_plasma_init(UNUSED(const device_t *info))
{
compaq_plasma_t *self = calloc(1, sizeof(compaq_plasma_t));
cga_init(&self->cga);
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_compaq_plasma);
self->cga.composite = 0;
self->cga.revision = 0;
self->cga.vram = malloc(0x8000);
self->internal_monitor = 1;
self->font_ram = malloc(0x2000);
cga_comp_init(self->cga.revision);
timer_set_callback(&self->cga.timer, compaq_plasma_poll);
timer_set_p(&self->cga.timer, self);
mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000,
compaq_plasma_read, NULL, NULL,
compaq_plasma_write, NULL, NULL,
NULL, MEM_MAPPING_EXTERNAL, self);
for (int i = 1; i <= 2; i++) {
io_sethandler(0x03c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x07c6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
io_sethandler(0x0bc6 + (i << 12), 0x0001, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
}
io_sethandler(0x03d0, 0x0010, compaq_plasma_in, NULL, NULL, compaq_plasma_out, NULL, NULL, self);
overscan_x = overscan_y = 16;
compaq_plasma_recalcattrs(self);
self->cga.rgb_type = device_get_config_int("rgb_type");
cga_palette = (self->cga.rgb_type << 1);
cgapal_rebuild();
compaq_plasma_mdaattr_rebuild();
return self;
}
static void
compaq_plasma_close(void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
free(self->cga.vram);
free(self->font_ram);
free(self);
}
static void
compaq_plasma_speed_changed(void *priv)
{
compaq_plasma_t *self = (compaq_plasma_t *) priv;
compaq_plasma_recalctimings(self);
}
const device_config_t compaq_plasma_config[] = {
// clang-format off
{
.name = "rgb_type",
.description = "RGB type",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "Color", .value = 0 },
{ .description = "Green Monochrome", .value = 1 },
{ .description = "Amber Monochrome", .value = 2 },
{ .description = "Gray Monochrome", .value = 3 },
{ .description = "" }
}
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t compaq_plasma_device = {
.name = "Compaq Plasma",
.internal_name = "compaq_plasma",
.flags = 0,
.local = 0,
.init = compaq_plasma_init,
.close = compaq_plasma_close,
.reset = NULL,
.available = NULL,
.speed_changed = compaq_plasma_speed_changed,
.force_redraw = NULL,
.config = compaq_plasma_config
};

View File

@@ -56,12 +56,12 @@ nga_recalctimings(nga_t *nga)
double _dispofftime;
double disptime;
if (nga->cga.cgamode & 1) {
disptime = nga->cga.crtc[0] + 1;
_dispontime = nga->cga.crtc[1];
if (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) {
disptime = nga->cga.crtc[CGA_CRTC_HTOTAL] + 1;
_dispontime = nga->cga.crtc[CGA_CRTC_HDISP];
} else {
disptime = (nga->cga.crtc[0] + 1) << 1;
_dispontime = nga->cga.crtc[1] << 1;
disptime = (nga->cga.crtc[CGA_CRTC_HTOTAL] + 1) << 1;
_dispontime = nga->cga.crtc[CGA_CRTC_HDISP] << 1;
}
_dispofftime = disptime - _dispontime;
@@ -148,7 +148,7 @@ nga_poll(void *priv)
{
nga_t *nga = (nga_t *) priv;
/* set cursor position in memory */
uint16_t ca = (nga->cga.crtc[15] | (nga->cga.crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
@@ -161,10 +161,10 @@ nga_poll(void *priv)
uint16_t dat2;
int cols[4];
int col;
int oldsc;
int scanline_old;
/* graphic mode and not high-res modes */
if ((nga->cga.cgamode & 2) && !(nga->cga.cgamode & 0x40)) {
if ((nga->cga.cgamode & CGA_MODE_FLAG_GRAPHICS) && !(nga->cga.cgamode & 0x40)) {
/* standard cga mode */
cga_poll(&nga->cga);
return;
@@ -174,10 +174,10 @@ nga_poll(void *priv)
timer_advance_u64(&nga->cga.timer, nga->cga.dispofftime);
nga->cga.cgastat |= 1;
nga->cga.linepos = 1;
oldsc = nga->cga.sc;
scanline_old = nga->cga.scanline;
/* if interlaced */
if ((nga->cga.crtc[8] & 3) == 3)
nga->cga.sc = ((nga->cga.sc << 1) + nga->cga.oddeven) & 7;
if ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3)
nga->cga.scanline = ((nga->cga.scanline << 1) + nga->cga.oddeven) & 7;
if (nga->cga.cgadispon) {
if (nga->cga.displine < nga->cga.firstline) {
nga->cga.firstline = nga->cga.displine;
@@ -185,11 +185,11 @@ nga_poll(void *priv)
}
nga->cga.lastline = nga->cga.displine;
/* 80-col */
if ((nga->cga.cgamode & 1) && !(nga->cga.cgamode & 2)) {
if ((nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) && !(nga->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) {
/* for each text column */
for (x = 0; x < nga->cga.crtc[1]; x++) {
for (x = 0; x < nga->cga.crtc[CGA_CRTC_HDISP]; x++) {
/* video output enabled */
if (nga->cga.cgamode & 8) {
if (nga->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
/* character */
chr = nga->cga.charbuffer[x << 1];
/* text attributes */
@@ -197,11 +197,11 @@ nga_poll(void *priv)
} else
chr = attr = 0;
/* check if cursor has to be drawn */
drawcursor = ((nga->cga.ma == ca) && nga->cga.con && nga->cga.cursoron);
drawcursor = ((nga->cga.memaddr == cursoraddr) && nga->cga.cursorvisible && nga->cga.cursoron);
/* set foreground */
cols[1] = (attr & 15) + 16;
/* blink active */
if (nga->cga.cgamode & 0x20) {
if (nga->cga.cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = ((attr >> 4) & 7) + 16;
/* attribute 7 active and not cursor */
if ((nga->cga.cgablink & 8) && (attr & 0x80) && !nga->cga.drawcursor) {
@@ -214,30 +214,30 @@ nga_poll(void *priv)
}
if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.scanline & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0];
buffer32->line[nga->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((nga->cga.scanline & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0];
}
nga->cga.ma++;
nga->cga.memaddr++;
}
}
/* 40-col */
else if (!(nga->cga.cgamode & 2)) {
else if (!(nga->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) {
/* for each text column */
for (x = 0; x < nga->cga.crtc[1]; x++) {
if (nga->cga.cgamode & 8) {
chr = nga->cga.vram[((nga->cga.ma << 1) & 0x3fff) + nga->base];
attr = nga->cga.vram[(((nga->cga.ma << 1) + 1) & 0x3fff) + nga->base];
for (x = 0; x < nga->cga.crtc[CGA_CRTC_HDISP]; x++) {
if (nga->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
chr = nga->cga.vram[((nga->cga.memaddr << 1) & 0x3fff) + nga->base];
attr = nga->cga.vram[(((nga->cga.memaddr << 1) + 1) & 0x3fff) + nga->base];
} else {
chr = attr = 0;
}
drawcursor = ((nga->cga.ma == ca) && nga->cga.con && nga->cga.cursoron);
drawcursor = ((nga->cga.memaddr == cursoraddr) && nga->cga.cursorvisible && nga->cga.cursoron);
/* set foreground */
cols[1] = (attr & 15) + 16;
/* blink active */
if (nga->cga.cgamode & 0x20) {
if (nga->cga.cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((nga->cga.cgablink & 8) && (attr & 0x80) && !nga->cga.drawcursor) {
/* set blinking */
@@ -250,19 +250,19 @@ nga_poll(void *priv)
if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.scanline & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.sc & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0];
buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[nga->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((nga->cga.scanline & 7) << 1) | nga->lineff] & (1 << (c ^ 7))) ? 1 : 0];
}
nga->cga.ma++;
nga->cga.memaddr++;
}
} else {
/* high res modes */
if (nga->cga.cgamode & 0x40) {
/* 640x400x2 mode */
if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & 0x10) {
if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) {
/*
* Scanlines are read in the following order:
* 0b8000-0b9f3f even scans (0,4,...)
@@ -270,14 +270,14 @@ nga_poll(void *priv)
* 0bc000-0bdf3f even scans (1,5,...)
* 0be000-0bff3f odd scans (3,7,...)
*/
dat2 = ((nga->cga.sc & 1) * 0x2000) | (nga->lineff * 0x4000);
dat2 = ((nga->cga.scanline & 1) * 0x2000) | (nga->lineff * 0x4000);
cols[0] = 0;
cols[1] = 15 + 16;
/* 640x400x4 mode */
} else {
cols[0] = (nga->cga.cgacol & 15) | 16;
col = (nga->cga.cgacol & 16) ? 24 : 16;
if (nga->cga.cgamode & 4) {
if (nga->cga.cgamode & CGA_MODE_FLAG_BW) {
cols[1] = col | 3; /* Cyan */
cols[2] = col | 4; /* Red */
cols[3] = col | 7; /* White */
@@ -297,22 +297,22 @@ nga_poll(void *priv)
* 0a8000-0abf3f even scans (2,6,...)
* 0ac000-0aff3f odd scans (3,7,...)
*/
dat2 = (nga->cga.sc & 1) * 0x4000;
dat2 = (nga->cga.scanline & 1) * 0x4000;
}
} else {
dat2 = (nga->cga.sc & 1) * 0x2000;
dat2 = (nga->cga.scanline & 1) * 0x2000;
cols[0] = 0;
cols[1] = (nga->cga.cgacol & 15) + 16;
}
/* for each text column */
for (x = 0; x < nga->cga.crtc[1]; x++) {
for (x = 0; x < nga->cga.crtc[CGA_CRTC_HDISP]; x++) {
/* video out */
if (nga->cga.cgamode & 8) {
if (nga->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
/* 640x400x2 */
if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & 0x10) {
if (nga->cga.cgamode & 0x4 || nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS) {
/* read two bytes at a time */
dat = (nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2] << 8) | nga->cga.vram[((nga->cga.ma << 1) & 0x1fff) + dat2 + 1];
dat = (nga->cga.vram[((nga->cga.memaddr << 1) & 0x1fff) + dat2] << 8) | nga->cga.vram[((nga->cga.memaddr << 1) & 0x1fff) + dat2 + 1];
/* each pixel is represented by one bit, so draw 16 pixels at a time */
/* crtc[1] is 40 column, so 40x16=640 pixels */
for (c = 0; c < 16; c++) {
@@ -322,13 +322,13 @@ nga_poll(void *priv)
/* 640x400x4 */
} else {
/* lines 2,3,6,7,etc. */
if (nga->cga.sc & 2)
if (nga->cga.scanline & 2)
/* read two bytes at a time */
dat = (nga->vram_64k[((nga->cga.ma << 1) & 0x7fff) + dat2] << 8) | nga->vram_64k[((nga->cga.ma << 1) & 0x7fff) + dat2 + 1];
dat = (nga->vram_64k[((nga->cga.memaddr << 1) & 0x7fff) + dat2] << 8) | nga->vram_64k[((nga->cga.memaddr << 1) & 0x7fff) + dat2 + 1];
/* lines 0,1,4,5,etc. */
else
/* read two bytes at a time */
dat = (nga->cga.vram[((nga->cga.ma << 1) & 0x7fff) + dat2] << 8) | nga->cga.vram[((nga->cga.ma << 1) & 0x7fff) + dat2 + 1];
dat = (nga->cga.vram[((nga->cga.memaddr << 1) & 0x7fff) + dat2] << 8) | nga->cga.vram[((nga->cga.memaddr << 1) & 0x7fff) + dat2 + 1];
/* each pixel is represented by two bits, so draw 8 pixels at a time */
/* crtc[1] is 80 column, so 80x8=640 pixels */
for (c = 0; c < 8; c++) {
@@ -339,7 +339,7 @@ nga_poll(void *priv)
} else {
dat = 0;
}
nga->cga.ma++;
nga->cga.memaddr++;
}
}
} else {
@@ -347,26 +347,26 @@ nga_poll(void *priv)
/* nga specific */
cols[0] = ((nga->cga.cgamode & 0x12) == 0x12) ? 0 : (nga->cga.cgacol & 15) + 16;
/* 80-col */
if (nga->cga.cgamode & 1) {
hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[1] << 3) + 16) << 2, cols[0]);
hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[1] << 3) + 16) << 2, cols[0]);
if (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) {
hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[CGA_CRTC_HDISP] << 3) + 16) << 2, cols[0]);
hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[CGA_CRTC_HDISP] << 3) + 16) << 2, cols[0]);
} else {
hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[1] << 4) + 16) << 2, cols[0]);
hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[1] << 4) + 16) << 2, cols[0]);
hline(buffer32, 0, (nga->cga.displine << 1), ((nga->cga.crtc[CGA_CRTC_HDISP] << 4) + 16) << 2, cols[0]);
hline(buffer32, 0, (nga->cga.displine << 1) + 1, ((nga->cga.crtc[CGA_CRTC_HDISP] << 4) + 16) << 2, cols[0]);
}
}
if (nga->cga.cgamode & 1)
if (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES)
/* set screen width */
x = (nga->cga.crtc[1] << 3) + 16;
x = (nga->cga.crtc[CGA_CRTC_HDISP] << 3) + 16;
else
x = (nga->cga.crtc[1] << 4) + 16;
x = (nga->cga.crtc[CGA_CRTC_HDISP] << 4) + 16;
video_process_8(x, nga->cga.displine);
nga->cga.sc = oldsc;
nga->cga.scanline = scanline_old;
/* vertical sync */
if (nga->cga.vc == nga->cga.crtc[7] && !nga->cga.sc)
if (nga->cga.vc == nga->cga.crtc[CGA_CRTC_VSYNC] && !nga->cga.scanline)
nga->cga.cgastat |= 8;
nga->cga.displine++;
if (nga->cga.displine >= 720)
@@ -380,8 +380,8 @@ nga_poll(void *priv)
nga->lineff ^= 1;
/* text mode or 640x400x2 */
if (nga->lineff && !((nga->cga.cgamode & 1) && (nga->cga.cgamode & 0x40))) {
nga->cga.ma = nga->cga.maback;
if (nga->lineff && !((nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) && (nga->cga.cgamode & 0x40))) {
nga->cga.memaddr = nga->cga.memaddr_backup;
/* 640x400x4 */
} else {
if (nga->cga.vsynctime) {
@@ -390,50 +390,49 @@ nga_poll(void *priv)
nga->cga.cgastat &= ~8;
}
/* cursor stop scanline */
if (nga->cga.sc == (nga->cga.crtc[11] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[11] & 31) >> 1))) {
nga->cga.con = 0;
nga->cga.coff = 1;
if (nga->cga.scanline == (nga->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.scanline == ((nga->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
nga->cga.cursorvisible = 0;
}
/* interlaced and max scanline per char reached */
if ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1))
nga->cga.maback = nga->cga.ma;
if ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.scanline == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
nga->cga.memaddr_backup = nga->cga.memaddr;
if (nga->cga.vadj) {
nga->cga.sc++;
nga->cga.sc &= 31;
nga->cga.ma = nga->cga.maback;
nga->cga.scanline++;
nga->cga.scanline &= 31;
nga->cga.memaddr = nga->cga.memaddr_backup;
nga->cga.vadj--;
if (!nga->cga.vadj) {
nga->cga.cgadispon = 1;
/* change start of displayed page (crtc 12-13) */
nga->cga.ma = nga->cga.maback = (nga->cga.crtc[13] | (nga->cga.crtc[12] << 8)) & 0x7fff;
nga->cga.sc = 0;
nga->cga.memaddr = nga->cga.memaddr_backup = (nga->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
nga->cga.scanline = 0;
}
/* nga specific */
/* end of character line reached */
} else if (nga->cga.sc == nga->cga.crtc[9] || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[9] >> 1))) {
nga->cga.maback = nga->cga.ma;
nga->cga.sc = 0;
} else if (nga->cga.scanline == nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.scanline == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) {
nga->cga.memaddr_backup = nga->cga.memaddr;
nga->cga.scanline = 0;
oldvc = nga->cga.vc;
nga->cga.vc++;
nga->cga.vc &= 127;
/* lines of character displayed */
if (nga->cga.vc == nga->cga.crtc[6])
if (nga->cga.vc == nga->cga.crtc[CGA_CRTC_VDISP])
nga->cga.cgadispon = 0;
/* total vertical lines */
if (oldvc == nga->cga.crtc[4]) {
if (oldvc == nga->cga.crtc[CGA_CRTC_VTOTAL]) {
nga->cga.vc = 0;
/* adjust vertical lines */
nga->cga.vadj = nga->cga.crtc[5];
nga->cga.vadj = nga->cga.crtc[CGA_CRTC_VTOTAL_ADJUST];
if (!nga->cga.vadj) {
nga->cga.cgadispon = 1;
/* change start of displayed page (crtc 12-13) */
nga->cga.ma = nga->cga.maback = (nga->cga.crtc[13] | (nga->cga.crtc[12] << 8)) & 0x7fff;
nga->cga.memaddr = nga->cga.memaddr_backup = (nga->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
}
/* cursor start */
switch (nga->cga.crtc[10] & 0x60) {
switch (nga->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) {
case 0x20:
nga->cga.cursoron = 0;
break;
@@ -446,18 +445,18 @@ nga_poll(void *priv)
}
}
/* vertical line position */
if (nga->cga.vc == nga->cga.crtc[7]) {
if (nga->cga.vc == nga->cga.crtc[CGA_CRTC_VSYNC]) {
nga->cga.cgadispon = 0;
nga->cga.displine = 0;
/* nga specific */
nga->cga.vsynctime = 16;
/* vsync pos */
if (nga->cga.crtc[7]) {
if (nga->cga.cgamode & 1)
if (nga->cga.crtc[CGA_CRTC_VSYNC]) {
if (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES)
/* set screen width */
x = (nga->cga.crtc[1] << 3) + 16;
x = (nga->cga.crtc[CGA_CRTC_HDISP] << 3) + 16;
else
x = (nga->cga.crtc[1] << 4) + 16;
x = (nga->cga.crtc[CGA_CRTC_HDISP] << 4) + 16;
nga->cga.lastline++;
xs_temp = x;
@@ -472,7 +471,7 @@ nga_poll(void *priv)
if (!enable_overscan)
xs_temp -= 16;
if ((nga->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
if ((nga->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
@@ -494,14 +493,14 @@ nga_poll(void *priv)
video_res_x = xsize;
video_res_y = ysize;
/* 80-col */
if ((nga->cga.cgamode & 1) && !(nga->cga.cgamode & 0x40)) {
if ((nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) && !(nga->cga.cgamode & 0x40)) {
video_res_x /= 8;
video_res_y /= (nga->cga.crtc[9] + 1) * 2;
video_res_y /= (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * 2;
video_bpp = 0;
/* 40-col */
} else if (!(nga->cga.cgamode & 2)) {
} else if (!(nga->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) {
video_res_x /= 16;
video_res_y /= (nga->cga.crtc[9] + 1) * 2;
video_res_y /= (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * 2;
video_bpp = 0;
} else if (nga->cga.cgamode & 0x40) {
video_res_x /= 8;
@@ -515,23 +514,23 @@ nga_poll(void *priv)
nga->cga.oddeven ^= 1;
}
} else {
nga->cga.sc++;
nga->cga.sc &= 31;
nga->cga.ma = nga->cga.maback;
nga->cga.scanline++;
nga->cga.scanline &= 31;
nga->cga.memaddr = nga->cga.memaddr_backup;
}
if (nga->cga.cgadispon)
nga->cga.cgastat &= ~1;
/* enable cursor if its scanline was reached */
if (nga->cga.sc == (nga->cga.crtc[10] & 31) || ((nga->cga.crtc[8] & 3) == 3 && nga->cga.sc == ((nga->cga.crtc[10] & 31) >> 1)))
nga->cga.con = 1;
if (nga->cga.scanline == (nga->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.scanline == ((nga->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1)))
nga->cga.cursorvisible = 1;
}
/* 80-columns */
if (nga->cga.cgadispon && (nga->cga.cgamode & 1)) {
if (nga->cga.cgadispon && (nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) {
/* for each character per line */
for (x = 0; x < (nga->cga.crtc[1] << 1); x++)
nga->cga.charbuffer[x] = nga->cga.vram[(((nga->cga.ma << 1) + x) & 0x3fff) + nga->base];
for (x = 0; x < (nga->cga.crtc[CGA_CRTC_HDISP] << 1); x++)
nga->cga.charbuffer[x] = nga->cga.vram[(((nga->cga.memaddr << 1) + x) & 0x3fff) + nga->base];
}
}
}

View File

@@ -65,12 +65,12 @@ ogc_recalctimings(ogc_t *ogc)
double _dispofftime;
double disptime;
if (ogc->cga.cgamode & 1) {
disptime = ogc->cga.crtc[0] + 1;
_dispontime = ogc->cga.crtc[1];
if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES) {
disptime = ogc->cga.crtc[CGA_CRTC_HTOTAL] + 1;
_dispontime = ogc->cga.crtc[CGA_CRTC_HDISP];
} else {
disptime = (ogc->cga.crtc[0] + 1) << 1;
_dispontime = ogc->cga.crtc[1] << 1;
disptime = (ogc->cga.crtc[CGA_CRTC_HTOTAL] + 1) << 1;
_dispontime = ogc->cga.crtc[CGA_CRTC_HDISP] << 1;
}
_dispofftime = disptime - _dispontime;
@@ -201,7 +201,7 @@ void
ogc_poll(void *priv)
{
ogc_t *ogc = (ogc_t *) priv;
uint16_t ca = (ogc->cga.crtc[15] | (ogc->cga.crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
@@ -213,14 +213,14 @@ ogc_poll(void *priv)
uint16_t dat;
uint16_t dat2;
int cols[4];
int oldsc;
int scanline_old;
int blink = 0;
int underline = 0;
// composito colore appare blu scuro
// Composite color appears dark blue
/* graphic mode and not mode 40h */
if (!(ogc->ctrl_3de & 0x1 || !(ogc->cga.cgamode & 2))) {
if (!(ogc->ctrl_3de & 0x1 || !(ogc->cga.cgamode & CGA_MODE_FLAG_GRAPHICS))) {
/* standard cga mode */
cga_poll(&ogc->cga);
return;
@@ -230,9 +230,9 @@ ogc_poll(void *priv)
timer_advance_u64(&ogc->cga.timer, ogc->cga.dispofftime);
ogc->cga.cgastat |= 1;
ogc->cga.linepos = 1;
oldsc = ogc->cga.sc;
if ((ogc->cga.crtc[8] & 3) == 3)
ogc->cga.sc = ((ogc->cga.sc << 1) + ogc->cga.oddeven) & 7;
scanline_old = ogc->cga.scanline;
if ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3)
ogc->cga.scanline = ((ogc->cga.scanline << 1) + ogc->cga.oddeven) & 7;
if (ogc->cga.cgadispon) {
if (ogc->cga.displine < ogc->cga.firstline) {
ogc->cga.firstline = ogc->cga.displine;
@@ -240,11 +240,11 @@ ogc_poll(void *priv)
}
ogc->cga.lastline = ogc->cga.displine;
/* 80-col */
if (ogc->cga.cgamode & 1) {
if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES) {
/* for each text column */
for (x = 0; x < ogc->cga.crtc[1]; x++) {
for (x = 0; x < ogc->cga.crtc[CGA_CRTC_HDISP]; x++) {
/* video output enabled */
if (ogc->cga.cgamode & 8) {
if (ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
/* character */
chr = ogc->cga.charbuffer[x << 1];
/* text attributes */
@@ -252,7 +252,7 @@ ogc_poll(void *priv)
} else
chr = attr = 0;
/* check if cursor has to be drawn */
drawcursor = ((ogc->cga.ma == ca) && ogc->cga.con && ogc->cga.cursoron);
drawcursor = ((ogc->cga.memaddr == cursoraddr) && ogc->cga.cursorvisible && ogc->cga.cursoron);
/* check if character underline mode should be set */
underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6));
if (underline) {
@@ -263,7 +263,7 @@ ogc_poll(void *priv)
/* set foreground */
cols[1] = (attr & 15) + 16;
/* blink active */
if (ogc->cga.cgamode & 0x20) {
if (ogc->cga.cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = ((attr >> 4) & 7) + 16;
/* attribute 7 active and not cursor */
if ((ogc->cga.cgablink & 8) && (attr & 0x80) && !ogc->cga.drawcursor) {
@@ -277,31 +277,31 @@ ogc_poll(void *priv)
blink = (attr & 0x80) * 8 + 7 + 16;
}
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (ogc->cga.sc == 7)) {
if (underline && (ogc->cga.scanline == 7)) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.scanline & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0];
buffer32->line[ogc->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((ogc->cga.scanline & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0];
}
ogc->cga.ma++;
ogc->cga.memaddr++;
}
}
/* 40-col */
else if (!(ogc->cga.cgamode & 2)) {
for (x = 0; x < ogc->cga.crtc[1]; x++) {
if (ogc->cga.cgamode & 8) {
chr = ogc->cga.vram[((ogc->cga.ma << 1) & 0x3fff) + ogc->base];
attr = ogc->cga.vram[(((ogc->cga.ma << 1) + 1) & 0x3fff) + ogc->base];
else if (!(ogc->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) {
for (x = 0; x < ogc->cga.crtc[CGA_CRTC_HDISP]; x++) {
if (ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
chr = ogc->cga.vram[((ogc->cga.memaddr << 1) & 0x3fff) + ogc->base];
attr = ogc->cga.vram[(((ogc->cga.memaddr << 1) + 1) & 0x3fff) + ogc->base];
} else {
chr = attr = 0;
}
drawcursor = ((ogc->cga.ma == ca) && ogc->cga.con && ogc->cga.cursoron);
drawcursor = ((ogc->cga.memaddr == cursoraddr) && ogc->cga.cursorvisible && ogc->cga.cursoron);
/* check if character underline mode should be set */
underline = ((ogc->ctrl_3de & 0x40) && (attr & 0x1) && !(attr & 0x6));
if (underline) {
@@ -312,7 +312,7 @@ ogc_poll(void *priv)
/* set foreground */
cols[1] = (attr & 15) + 16;
/* blink active */
if (ogc->cga.cgamode & 0x20) {
if (ogc->cga.cgamode & CGA_MODE_FLAG_BLINK) {
cols[0] = ((attr >> 4) & 7) + 16;
if ((ogc->cga.cgablink & 8) && (attr & 0x80) && !ogc->cga.drawcursor) {
/* set blinking */
@@ -326,40 +326,40 @@ ogc_poll(void *priv)
}
/* character underline active and 7th row of pixels in character height being drawn */
if (underline && (ogc->cga.sc == 7)) {
if (underline && (ogc->cga.scanline == 7)) {
/* for each pixel in character width */
for (c = 0; c < 8; c++)
buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.scanline & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.sc & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0];
buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[ogc->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((ogc->cga.scanline & 7) << 1) | ogc->lineff] & (1 << (c ^ 7))) ? 1 : 0];
}
ogc->cga.ma++;
ogc->cga.memaddr++;
}
} else {
/* 640x400 mode */
if (ogc->ctrl_3de & 1) {
dat2 = ((ogc->cga.sc & 1) * 0x4000) | (ogc->lineff * 0x2000);
dat2 = ((ogc->cga.scanline & 1) * 0x4000) | (ogc->lineff * 0x2000);
cols[0] = 0;
cols[1] = 15 + 16;
} else {
dat2 = (ogc->cga.sc & 1) * 0x2000;
dat2 = (ogc->cga.scanline & 1) * 0x2000;
cols[0] = 0;
cols[1] = (ogc->cga.cgacol & 15) + 16;
}
for (x = 0; x < ogc->cga.crtc[1]; x++) {
for (x = 0; x < ogc->cga.crtc[CGA_CRTC_HDISP]; x++) {
/* video out */
if (ogc->cga.cgamode & 8) {
dat = (ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2] << 8) | ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2 + 1];
if (ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
dat = (ogc->cga.vram[((ogc->cga.memaddr << 1) & 0x1fff) + dat2] << 8) | ogc->cga.vram[((ogc->cga.memaddr << 1) & 0x1fff) + dat2 + 1];
} else {
dat = 0;
}
ogc->cga.ma++;
ogc->cga.memaddr++;
for (c = 0; c < 16; c++) {
buffer32->line[ogc->cga.displine][(x << 4) + c + 8] = cols[dat >> 15];
@@ -370,22 +370,22 @@ ogc_poll(void *priv)
} else {
/* ogc specific */
cols[0] = ((ogc->cga.cgamode & 0x12) == 0x12) ? 0 : (ogc->cga.cgacol & 15) + 16;
if (ogc->cga.cgamode & 1)
hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[1] << 3) + 16) << 2, cols[0]);
if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES)
hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[CGA_CRTC_HDISP] << 3) + 16) << 2, cols[0]);
else
hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[1] << 4) + 16) << 2, cols[0]);
hline(buffer32, 0, ogc->cga.displine, ((ogc->cga.crtc[CGA_CRTC_HDISP] << 4) + 16) << 2, cols[0]);
}
/* 80 columns */
if (ogc->cga.cgamode & 1)
x = (ogc->cga.crtc[1] << 3) + 16;
if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES)
x = (ogc->cga.crtc[CGA_CRTC_HDISP] << 3) + 16;
else
x = (ogc->cga.crtc[1] << 4) + 16;
x = (ogc->cga.crtc[CGA_CRTC_HDISP] << 4) + 16;
video_process_8(x, ogc->cga.displine);
ogc->cga.sc = oldsc;
if (ogc->cga.vc == ogc->cga.crtc[7] && !ogc->cga.sc)
ogc->cga.scanline = scanline_old;
if (ogc->cga.vc == ogc->cga.crtc[CGA_CRTC_VSYNC] && !ogc->cga.scanline)
ogc->cga.cgastat |= 8;
ogc->cga.displine++;
if (ogc->cga.displine >= 720)
@@ -398,48 +398,47 @@ ogc_poll(void *priv)
/* ogc specific */
ogc->lineff ^= 1;
if (ogc->lineff) {
ogc->cga.ma = ogc->cga.maback;
ogc->cga.memaddr = ogc->cga.memaddr_backup;
} else {
if (ogc->cga.vsynctime) {
ogc->cga.vsynctime--;
if (!ogc->cga.vsynctime)
ogc->cga.cgastat &= ~8;
}
if (ogc->cga.sc == (ogc->cga.crtc[11] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[11] & 31) >> 1))) {
ogc->cga.con = 0;
ogc->cga.coff = 1;
if (ogc->cga.scanline == (ogc->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.scanline == ((ogc->cga.crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
ogc->cga.cursorvisible = 0;
}
if ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1))
ogc->cga.maback = ogc->cga.ma;
if ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.scanline == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
ogc->cga.memaddr_backup = ogc->cga.memaddr;
if (ogc->cga.vadj) {
ogc->cga.sc++;
ogc->cga.sc &= 31;
ogc->cga.ma = ogc->cga.maback;
ogc->cga.scanline++;
ogc->cga.scanline &= 31;
ogc->cga.memaddr = ogc->cga.memaddr_backup;
ogc->cga.vadj--;
if (!ogc->cga.vadj) {
ogc->cga.cgadispon = 1;
ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[13] | (ogc->cga.crtc[12] << 8)) & 0x3fff;
ogc->cga.sc = 0;
ogc->cga.memaddr = ogc->cga.memaddr_backup = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
ogc->cga.scanline = 0;
}
// potrebbe dare problemi con composito
} else if (ogc->cga.sc == ogc->cga.crtc[9] || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[9] >> 1))) {
ogc->cga.maback = ogc->cga.ma;
ogc->cga.sc = 0;
// may cause problems with composite
} else if (ogc->cga.scanline == ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.scanline == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) {
ogc->cga.memaddr_backup = ogc->cga.memaddr;
ogc->cga.scanline = 0;
oldvc = ogc->cga.vc;
ogc->cga.vc++;
ogc->cga.vc &= 127;
if (ogc->cga.vc == ogc->cga.crtc[6])
if (ogc->cga.vc == ogc->cga.crtc[CGA_CRTC_VDISP])
ogc->cga.cgadispon = 0;
if (oldvc == ogc->cga.crtc[4]) {
if (oldvc == ogc->cga.crtc[CGA_CRTC_VTOTAL]) {
ogc->cga.vc = 0;
ogc->cga.vadj = ogc->cga.crtc[5];
ogc->cga.vadj = ogc->cga.crtc[CGA_CRTC_VTOTAL_ADJUST];
if (!ogc->cga.vadj) {
ogc->cga.cgadispon = 1;
ogc->cga.ma = ogc->cga.maback = (ogc->cga.crtc[13] | (ogc->cga.crtc[12] << 8)) & 0x3fff;
ogc->cga.memaddr = ogc->cga.memaddr_backup = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
}
switch (ogc->cga.crtc[10] & 0x60) {
switch (ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) {
case 0x20:
ogc->cga.cursoron = 0;
break;
@@ -451,16 +450,16 @@ ogc_poll(void *priv)
break;
}
}
if (ogc->cga.vc == ogc->cga.crtc[7]) {
if (ogc->cga.vc == ogc->cga.crtc[CGA_CRTC_VSYNC]) {
ogc->cga.cgadispon = 0;
ogc->cga.displine = 0;
/* ogc specific */
ogc->cga.vsynctime = (ogc->cga.crtc[3] >> 4) + 1;
if (ogc->cga.crtc[7]) {
if (ogc->cga.cgamode & 1)
x = (ogc->cga.crtc[1] << 3) + 16;
ogc->cga.vsynctime = (ogc->cga.crtc[CGA_CRTC_HSYNC_WIDTH] >> 4) + 1;
if (ogc->cga.crtc[CGA_CRTC_VSYNC]) {
if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES)
x = (ogc->cga.crtc[CGA_CRTC_HDISP] << 3) + 16;
else
x = (ogc->cga.crtc[1] << 4) + 16;
x = (ogc->cga.crtc[CGA_CRTC_HDISP] << 4) + 16;
ogc->cga.lastline++;
xs_temp = x;
@@ -475,7 +474,7 @@ ogc_poll(void *priv)
if (!enable_overscan)
xs_temp -= 16;
if ((ogc->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
if ((ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
@@ -497,14 +496,14 @@ ogc_poll(void *priv)
video_res_x = xsize;
video_res_y = ysize;
/* 80-col */
if (ogc->cga.cgamode & 1) {
if (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES) {
video_res_x /= 8;
video_res_y /= (ogc->cga.crtc[9] + 1) * 2;
video_res_y /= (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * 2;
video_bpp = 0;
/* 40-col */
} else if (!(ogc->cga.cgamode & 2)) {
} else if (!(ogc->cga.cgamode & CGA_MODE_FLAG_GRAPHICS)) {
video_res_x /= 16;
video_res_y /= (ogc->cga.crtc[9] + 1) * 2;
video_res_y /= (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * 2;
video_bpp = 0;
} else if (!(ogc->ctrl_3de & 1)) {
video_res_y /= 2;
@@ -517,21 +516,21 @@ ogc_poll(void *priv)
ogc->cga.oddeven ^= 1;
}
} else {
ogc->cga.sc++;
ogc->cga.sc &= 31;
ogc->cga.ma = ogc->cga.maback;
ogc->cga.scanline++;
ogc->cga.scanline &= 31;
ogc->cga.memaddr = ogc->cga.memaddr_backup;
}
if (ogc->cga.cgadispon)
ogc->cga.cgastat &= ~1;
if (ogc->cga.sc == (ogc->cga.crtc[10] & 31) || ((ogc->cga.crtc[8] & 3) == 3 && ogc->cga.sc == ((ogc->cga.crtc[10] & 31) >> 1)))
ogc->cga.con = 1;
if (ogc->cga.scanline == (ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.scanline == ((ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 31) >> 1)))
ogc->cga.cursorvisible = 1;
}
/* 80-columns */
if (ogc->cga.cgadispon && (ogc->cga.cgamode & 1)) {
for (x = 0; x < (ogc->cga.crtc[1] << 1); x++)
ogc->cga.charbuffer[x] = ogc->cga.vram[(((ogc->cga.ma << 1) + x) & 0x3fff) + ogc->base];
if (ogc->cga.cgadispon && (ogc->cga.cgamode & CGA_MODE_FLAG_HIGHRES)) {
for (x = 0; x < (ogc->cga.crtc[CGA_CRTC_HDISP] << 1); x++)
ogc->cga.charbuffer[x] = ogc->cga.vram[(((ogc->cga.memaddr << 1) + x) & 0x3fff) + ogc->base];
}
}
}

View File

@@ -245,25 +245,25 @@ t1000_text_row80(t1000_t *t1000)
int bold;
int blink;
uint16_t addr;
uint8_t sc;
uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff;
uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff;
uint8_t scanline;
uint16_t memaddr = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
uint16_t cursoraddr = (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
sc = (t1000->displine) & 7;
addr = ((ma & ~1) + (t1000->displine >> 3) * 80) * 2;
ma += (t1000->displine >> 3) * 80;
scanline = (t1000->displine) & 7;
addr = ((memaddr & ~1) + (t1000->displine >> 3) * 80) * 2;
memaddr += (t1000->displine >> 3) * 80;
if ((t1000->cga.crtc[10] & 0x60) == 0x20) {
if ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) {
cursorline = 0;
} else {
cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && ((t1000->cga.crtc[11] & 0x0F) >= sc);
cursorline = ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= scanline) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= scanline);
}
for (uint8_t x = 0; x < 80; x++) {
chr = t1000->vram[(addr + 2 * x) & 0x3FFF];
attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF];
drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16));
drawcursor = ((memaddr == cursoraddr) && cursorline && (t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t1000->cga.cgablink & 16));
blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
if (t1000->video_options & 1)
bold = boldcols[attr] ? chr : chr + 256;
@@ -272,7 +272,7 @@ t1000_text_row80(t1000_t *t1000)
if (t1000->video_options & 2)
bold += 512;
if (t1000->cga.cgamode & 0x20) /* Blink */
if (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) /* Blink */
{
cols[1] = blinkcols[attr][1];
cols[0] = blinkcols[attr][0];
@@ -284,13 +284,13 @@ t1000_text_row80(t1000_t *t1000)
}
if (drawcursor) {
for (uint8_t c = 0; c < 8; c++) {
(buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey);
(buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey);
}
} else {
for (uint8_t c = 0; c < 8; c++)
(buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0];
(buffer32->line[t1000->displine])[(x << 3) + c] = cols[(fontdat[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0];
}
++ma;
++memaddr;
}
}
@@ -306,25 +306,25 @@ t1000_text_row40(t1000_t *t1000)
int bold;
int blink;
uint16_t addr;
uint8_t sc;
uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff;
uint16_t ca = (t1000->cga.crtc[15] | (t1000->cga.crtc[14] << 8)) & 0x3fff;
uint8_t scanline;
uint16_t memaddr = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
uint16_t cursoraddr = (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
sc = (t1000->displine) & 7;
addr = ((ma & ~1) + (t1000->displine >> 3) * 40) * 2;
ma += (t1000->displine >> 3) * 40;
scanline = (t1000->displine) & 7;
addr = ((memaddr & ~1) + (t1000->displine >> 3) * 40) * 2;
memaddr += (t1000->displine >> 3) * 40;
if ((t1000->cga.crtc[10] & 0x60) == 0x20) {
if ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) {
cursorline = 0;
} else {
cursorline = ((t1000->cga.crtc[10] & 0x0F) <= sc) && ((t1000->cga.crtc[11] & 0x0F) >= sc);
cursorline = ((t1000->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= scanline) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= scanline);
}
for (uint8_t x = 0; x < 40; x++) {
chr = t1000->vram[(addr + 2 * x) & 0x3FFF];
attr = t1000->vram[(addr + 2 * x + 1) & 0x3FFF];
drawcursor = ((ma == ca) && cursorline && (t1000->cga.cgamode & 8) && (t1000->cga.cgablink & 16));
drawcursor = ((memaddr == cursoraddr) && cursorline && (t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t1000->cga.cgablink & 16));
blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
blink = ((t1000->cga.cgablink & 16) && (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
if (t1000->video_options & 1)
bold = boldcols[attr] ? chr : chr + 256;
@@ -333,7 +333,7 @@ t1000_text_row40(t1000_t *t1000)
if (t1000->video_options & 2)
bold += 512;
if (t1000->cga.cgamode & 0x20) /* Blink */
if (t1000->cga.cgamode & CGA_MODE_FLAG_BLINK) /* Blink */
{
cols[1] = blinkcols[attr][1];
cols[0] = blinkcols[attr][0];
@@ -345,14 +345,14 @@ t1000_text_row40(t1000_t *t1000)
}
if (drawcursor) {
for (uint8_t c = 0; c < 8; c++) {
(buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey);
(buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ (blue ^ grey);
}
} else {
for (uint8_t c = 0; c < 8; c++) {
(buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][sc] & (1 << (c ^ 7))) ? 1 : 0];
(buffer32->line[t1000->displine])[(x << 4) + c * 2] = (buffer32->line[t1000->displine])[(x << 4) + c * 2 + 1] = cols[(fontdat[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0];
}
}
++ma;
++memaddr;
}
}
@@ -366,9 +366,9 @@ t1000_cgaline6(t1000_t *t1000)
uint32_t fg = (t1000->cga.cgacol & 0x0F) ? blue : grey;
uint32_t bg = grey;
uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff;
uint16_t memaddr = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((ma & ~1) << 1);
addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((memaddr & ~1) << 1);
for (uint8_t x = 0; x < 80; x++) {
dat = t1000->vram[addr & 0x3FFF];
@@ -376,7 +376,7 @@ t1000_cgaline6(t1000_t *t1000)
for (uint8_t c = 0; c < 8; c++) {
ink = (dat & 0x80) ? fg : bg;
if (!(t1000->cga.cgamode & 8))
if (!(t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE))
ink = grey;
(buffer32->line[t1000->displine])[x * 8 + c] = ink;
dat = dat << 1;
@@ -395,8 +395,8 @@ t1000_cgaline4(t1000_t *t1000)
uint32_t ink1;
uint16_t addr;
uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff;
addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((ma & ~1) << 1);
uint16_t memaddr = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
addr = ((t1000->displine) & 1) * 0x2000 + (t1000->displine >> 1) * 80 + ((memaddr & ~1) << 1);
for (uint8_t x = 0; x < 80; x++) {
dat = t1000->vram[addr & 0x3FFF];
@@ -404,7 +404,7 @@ t1000_cgaline4(t1000_t *t1000)
for (uint8_t c = 0; c < 4; c++) {
pattern = (dat & 0xC0) >> 6;
if (!(t1000->cga.cgamode & 8))
if (!(t1000->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE))
pattern = 0;
switch (pattern & 3) {
@@ -479,7 +479,7 @@ t1000_poll(void *priv)
/* Graphics */
if (t1000->cga.cgamode & 0x02) {
if (t1000->cga.cgamode & 0x10)
if (t1000->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)
t1000_cgaline6(t1000);
else
t1000_cgaline4(t1000);
@@ -532,7 +532,7 @@ t1000_poll(void *priv)
video_res_y = T1000_YSIZE;
if (t1000->cga.cgamode & 0x02) {
if (t1000->cga.cgamode & 0x10)
if (t1000->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)
video_bpp = 1;
else
video_bpp = 2;

View File

@@ -169,8 +169,8 @@ t3100e_out(uint16_t addr, uint8_t val, void *priv)
t3100e_recalctimings(t3100e);
return;
case 0x3D8: /* CGA control register */
case 0x3D9: /* CGA colour register */
case CGA_REGISTER_MODE_CONTROL: /* CGA control register */
case CGA_REGISTER_COLOR_SELECT: /* CGA colour register */
cga_out(addr, val, &t3100e->cga);
return;
@@ -254,25 +254,25 @@ t3100e_text_row80(t3100e_t *t3100e)
int bold;
int blink;
uint16_t addr;
uint8_t sc;
uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff;
uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff;
uint8_t scanline;
uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
uint16_t cursoraddr = (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff;
sc = (t3100e->displine) & 15;
addr = ((ma & ~1) + (t3100e->displine >> 4) * 80) * 2;
ma += (t3100e->displine >> 4) * 80;
scanline = (t3100e->displine) & 15;
addr = ((memaddr & ~1) + (t3100e->displine >> 4) * 80) * 2;
memaddr += (t3100e->displine >> 4) * 80;
if ((t3100e->cga.crtc[10] & 0x60) == 0x20) {
if ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) {
cursorline = 0;
} else {
cursorline = ((t3100e->cga.crtc[10] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[11] & 0x0F) * 2 >= sc);
cursorline = ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) * 2 <= scanline) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= scanline);
}
for (uint8_t x = 0; x < 80; x++) {
chr = t3100e->vram[(addr + 2 * x) & 0x7FFF];
attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF];
drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16));
drawcursor = ((memaddr == cursoraddr) && cursorline && (t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t3100e->cga.cgablink & 16));
blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
if (t3100e->video_options & 4)
bold = boldcols[attr] ? chr + 256 : chr;
@@ -280,7 +280,7 @@ t3100e_text_row80(t3100e_t *t3100e)
bold = boldcols[attr] ? chr : chr + 256;
bold += 512 * (t3100e->video_options & 3);
if (t3100e->cga.cgamode & 0x20) /* Blink */
if (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) /* Blink */
{
cols[1] = blinkcols[attr][1];
cols[0] = blinkcols[attr][0];
@@ -292,13 +292,13 @@ t3100e_text_row80(t3100e_t *t3100e)
}
if (drawcursor) {
for (uint8_t c = 0; c < 8; c++) {
(buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
(buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
}
} else {
for (uint8_t c = 0; c < 8; c++)
(buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0];
(buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0];
}
++ma;
++memaddr;
}
}
@@ -315,25 +315,25 @@ t3100e_text_row40(t3100e_t *t3100e)
int bold;
int blink;
uint16_t addr;
uint8_t sc;
uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff;
uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff;
uint8_t scanline;
uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
uint16_t cursoraddr = (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x7fff;
sc = (t3100e->displine) & 15;
addr = ((ma & ~1) + (t3100e->displine >> 4) * 40) * 2;
ma += (t3100e->displine >> 4) * 40;
scanline = (t3100e->displine) & 15;
addr = ((memaddr & ~1) + (t3100e->displine >> 4) * 40) * 2;
memaddr += (t3100e->displine >> 4) * 40;
if ((t3100e->cga.crtc[10] & 0x60) == 0x20) {
if ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) {
cursorline = 0;
} else {
cursorline = ((t3100e->cga.crtc[10] & 0x0F) * 2 <= sc) && ((t3100e->cga.crtc[11] & 0x0F) * 2 >= sc);
cursorline = ((t3100e->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) * 2 <= scanline) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= scanline);
}
for (uint8_t x = 0; x < 40; x++) {
chr = t3100e->vram[(addr + 2 * x) & 0x7FFF];
attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF];
drawcursor = ((ma == ca) && cursorline && (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16));
drawcursor = ((memaddr == cursoraddr) && cursorline && (t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (t3100e->cga.cgablink & 16));
blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
if (t3100e->video_options & 4)
bold = boldcols[attr] ? chr + 256 : chr;
@@ -341,7 +341,7 @@ t3100e_text_row40(t3100e_t *t3100e)
bold = boldcols[attr] ? chr : chr + 256;
bold += 512 * (t3100e->video_options & 3);
if (t3100e->cga.cgamode & 0x20) /* Blink */
if (t3100e->cga.cgamode & CGA_MODE_FLAG_BLINK) /* Blink */
{
cols[1] = blinkcols[attr][1];
cols[0] = blinkcols[attr][0];
@@ -353,14 +353,14 @@ t3100e_text_row40(t3100e_t *t3100e)
}
if (drawcursor) {
for (c = 0; c < 8; c++) {
(buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
(buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black);
}
} else {
for (c = 0; c < 8; c++) {
(buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0];
(buffer32->line[t3100e->displine])[(x << 4) + c * 2] = (buffer32->line[t3100e->displine])[(x << 4) + c * 2 + 1] = cols[(fontdatm[bold][scanline] & (1 << (c ^ 7))) ? 1 : 0];
}
}
++ma;
++memaddr;
}
}
@@ -374,13 +374,13 @@ t3100e_cgaline6(t3100e_t *t3100e)
uint32_t fg = (t3100e->cga.cgacol & 0x0F) ? amber : black;
uint32_t bg = black;
uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff;
uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
if (t3100e->cga.crtc[9] == 3) /* 640*400 */
if (t3100e->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] == 3) /* 640*400 */
{
addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1);
addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((memaddr & ~1) << 1);
} else {
addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1);
addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((memaddr & ~1) << 1);
}
for (uint8_t x = 0; x < 80; x++) {
dat = t3100e->vram[addr & 0x7FFF];
@@ -388,7 +388,7 @@ t3100e_cgaline6(t3100e_t *t3100e)
for (uint8_t c = 0; c < 8; c++) {
ink = (dat & 0x80) ? fg : bg;
if (!(t3100e->cga.cgamode & 8))
if (!(t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE))
ink = black;
(buffer32->line[t3100e->displine])[x * 8 + c] = ink;
dat = dat << 1;
@@ -407,13 +407,13 @@ t3100e_cgaline4(t3100e_t *t3100e)
uint32_t ink1 = 0;
uint16_t addr;
uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff;
if (t3100e->cga.crtc[9] == 3) /* 320*400 undocumented */
uint16_t memaddr = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
if (t3100e->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] == 3) /* 320*400 undocumented */
{
addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1);
addr = ((t3100e->displine) & 1) * 0x2000 + ((t3100e->displine >> 1) & 1) * 0x4000 + (t3100e->displine >> 2) * 80 + ((memaddr & ~1) << 1);
} else /* 320*200 */
{
addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((ma & ~1) << 1);
addr = ((t3100e->displine >> 1) & 1) * 0x2000 + (t3100e->displine >> 2) * 80 + ((memaddr & ~1) << 1);
}
for (uint8_t x = 0; x < 80; x++) {
dat = t3100e->vram[addr & 0x7FFF];
@@ -421,7 +421,7 @@ t3100e_cgaline4(t3100e_t *t3100e)
for (uint8_t c = 0; c < 4; c++) {
pattern = (dat & 0xC0) >> 6;
if (!(t3100e->cga.cgamode & 8))
if (!(t3100e->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE))
pattern = 0;
switch (pattern & 3) {
@@ -497,12 +497,12 @@ t3100e_poll(void *priv)
}
/* Graphics */
if (t3100e->cga.cgamode & 0x02) {
if (t3100e->cga.cgamode & 0x10)
if (t3100e->cga.cgamode & CGA_MODE_FLAG_GRAPHICS) {
if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)
t3100e_cgaline6(t3100e);
else
t3100e_cgaline4(t3100e);
} else if (t3100e->cga.cgamode & 0x01) /* High-res text */
} else if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES) /* High-res text */
{
t3100e_text_row80(t3100e);
} else {
@@ -550,8 +550,8 @@ t3100e_poll(void *priv)
video_res_x = T3100E_XSIZE;
video_res_y = T3100E_YSIZE;
if (t3100e->cga.cgamode & 0x02) {
if (t3100e->cga.cgamode & 0x10)
if (t3100e->cga.cgamode & CGA_MODE_FLAG_GRAPHICS) {
if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)
video_bpp = 1;
else
video_bpp = 2;

View File

@@ -1098,7 +1098,7 @@ chips_69000_recalctimings(svga_t *svga)
svga->hblank_end_val = ((svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00)) | (svga->crtc[0x3c] & 0b11000000);
svga->hblank_end_mask = 0xff;
svga->ma_latch |= (svga->crtc[0x40] & 0xF) << 16;
svga->memaddr_latch |= (svga->crtc[0x40] & 0xF) << 16;
svga->rowoffset |= (svga->crtc[0x41] & 0xF) << 8;
svga->interlace = !!(svga->crtc[0x70] & 0x80);
@@ -2044,7 +2044,7 @@ chips_69000_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);

View File

@@ -575,7 +575,7 @@ gd54xx_overlay_draw(svga_t *svga, int displine)
uint8_t *src = &svga->vram[(svga->overlay_latch.addr << shift) & svga->vram_mask];
int bpp = svga->bpp;
int bytesperpix = (bpp + 7) / 8;
uint8_t *src2 = &svga->vram[(svga->ma - (svga->hdisp * bytesperpix)) & svga->vram_display_mask];
uint8_t *src2 = &svga->vram[(svga->memaddr - (svga->hdisp * bytesperpix)) & svga->vram_display_mask];
int occl;
int ckval;
@@ -1255,7 +1255,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) +
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) +
((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
@@ -1875,7 +1875,7 @@ gd54xx_recalctimings(svga_t *svga)
} else if (svga->gdcreg[5] & 0x40)
svga->render = svga_render_8bpp_lowres;
svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15);
svga->memaddr_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15);
svga->bpp = 8;

View File

@@ -1,502 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the Compaq CGA graphics cards.
*
*
*
* Authors: John Elliott, <jce@seasip.info>
* Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2019 John Elliott.
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/video.h>
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#define CGA_RGB 0
#define CGA_COMPOSITE 1
static uint32_t vflags;
static uint8_t mdaattr[256][2][2];
typedef struct compaq_cga_t {
cga_t cga;
} compaq_cga_t;
#ifdef ENABLE_COMPAQ_CGA_LOG
int compaq_cga_do_log = ENABLE_COMPAQ_CGA_LOG;
static void
compaq_cga_log(const char *fmt, ...)
{
va_list ap;
if (compaq_cga_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define compaq_cga_log(fmt, ...)
#endif
void
compaq_cga_recalctimings(compaq_cga_t *self)
{
double _dispontime;
double _dispofftime;
double disptime;
disptime = self->cga.crtc[0] + 1;
_dispontime = self->cga.crtc[1];
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
self->cga.dispontime = (uint64_t) (_dispontime);
self->cga.dispofftime = (uint64_t) (_dispofftime);
}
void
compaq_cga_poll(void *priv)
{
compaq_cga_t *self = (compaq_cga_t *) priv;
uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
int xs_temp;
int ys_temp;
int oldvc;
uint8_t chr;
uint8_t attr;
uint8_t border;
uint8_t cols[4];
int oldsc;
int underline = 0;
int blink = 0;
/* If in graphics mode or character height is not 13, behave as CGA */
if ((self->cga.cgamode & 0x12) || (self->cga.crtc[9] != 13)) {
overscan_x = overscan_y = 16;
cga_poll(&self->cga);
return;
} else
overscan_x = overscan_y = 0;
/* We are in Compaq 350-line CGA territory */
if (!self->cga.linepos) {
timer_advance_u64(&self->cga.timer, self->cga.dispofftime);
self->cga.cgastat |= 1;
self->cga.linepos = 1;
oldsc = self->cga.sc;
if ((self->cga.crtc[8] & 3) == 3)
self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7;
if (self->cga.cgadispon) {
if (self->cga.displine < self->cga.firstline) {
self->cga.firstline = self->cga.displine;
video_wait_for_buffer();
compaq_cga_log("Firstline %i\n", self->cga.firstline);
}
self->cga.lastline = self->cga.displine;
cols[0] = (self->cga.cgacol & 15) + 16;
for (c = 0; c < 8; c++) {
buffer32->line[self->cga.displine][c] = cols[0];
if (self->cga.cgamode & 1)
buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 3) + 8] = cols[0];
else
buffer32->line[self->cga.displine][c + (self->cga.crtc[1] << 4) + 8] = cols[0];
}
if (self->cga.cgamode & 1) {
for (x = 0; x < self->cga.crtc[1]; x++) {
chr = self->cga.charbuffer[x << 1];
attr = self->cga.charbuffer[(x << 1) + 1];
drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron);
if (vflags) {
underline = 0;
blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
}
if (vflags && (self->cga.cgamode & 0x80)) {
cols[0] = mdaattr[attr][blink][0];
cols[1] = mdaattr[attr][blink][1];
if ((self->cga.sc == 12) && ((attr & 7) == 1))
underline = 1;
} else if (self->cga.cgamode & 0x20) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if (vflags) {
if (blink)
cols[1] = cols[0];
} else {
if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor)
cols[1] = cols[0];
}
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
if (vflags && underline) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c + 8] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
}
self->cga.ma++;
}
} else {
for (x = 0; x < self->cga.crtc[1]; x++) {
chr = self->cga.vram[(self->cga.ma << 1) & 0x3fff];
attr = self->cga.vram[((self->cga.ma << 1) + 1) & 0x3fff];
drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron);
if (vflags) {
underline = 0;
blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
}
if (vflags && (self->cga.cgamode & 0x80)) {
cols[0] = mdaattr[attr][blink][0];
cols[1] = mdaattr[attr][blink][1];
if (self->cga.sc == 12 && (attr & 7) == 1)
underline = 1;
} else if (self->cga.cgamode & 0x20) {
cols[1] = (attr & 15) + 16;
cols[0] = ((attr >> 4) & 7) + 16;
if (vflags) {
if (blink)
cols[1] = cols[0];
} else {
if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor)
cols[1] = cols[0];
}
} else {
cols[1] = (attr & 15) + 16;
cols[0] = (attr >> 4) + 16;
}
self->cga.ma++;
if (vflags && underline) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 9] = mdaattr[attr][blink][1];
} else if (drawcursor) {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15;
} else {
for (c = 0; c < 8; c++)
buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 8] = buffer32->line[self->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0];
}
}
}
} else {
cols[0] = (self->cga.cgacol & 15) + 16;
if (self->cga.cgamode & 1)
hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]);
else
hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]);
}
if (self->cga.cgamode & 1)
x = (self->cga.crtc[1] << 3) + 16;
else
x = (self->cga.crtc[1] << 4) + 16;
if (self->cga.composite) {
if (self->cga.cgamode & 0x10)
border = 0x00;
else
border = self->cga.cgacol & 0x0f;
if (vflags)
Composite_Process(self->cga.cgamode & 0x7f, border, x >> 2, buffer32->line[self->cga.displine]);
else
Composite_Process(self->cga.cgamode, border, x >> 2, buffer32->line[self->cga.displine]);
} else
video_process_8(x, self->cga.displine);
self->cga.sc = oldsc;
if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc)
self->cga.cgastat |= 8;
self->cga.displine++;
if (self->cga.displine >= 500)
self->cga.displine = 0;
} else {
timer_advance_u64(&self->cga.timer, self->cga.dispontime);
self->cga.linepos = 0;
if (self->cga.vsynctime) {
self->cga.vsynctime--;
if (!self->cga.vsynctime)
self->cga.cgastat &= ~8;
}
if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) {
self->cga.con = 0;
self->cga.coff = 1;
}
if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1))
self->cga.maback = self->cga.ma;
if (self->cga.vadj) {
self->cga.sc++;
self->cga.sc &= 31;
self->cga.ma = self->cga.maback;
self->cga.vadj--;
if (!self->cga.vadj) {
self->cga.cgadispon = 1;
self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff;
self->cga.sc = 0;
}
} else if (self->cga.sc == self->cga.crtc[9]) {
self->cga.maback = self->cga.ma;
self->cga.sc = 0;
oldvc = self->cga.vc;
self->cga.vc++;
self->cga.vc &= 127;
if (self->cga.vc == self->cga.crtc[6])
self->cga.cgadispon = 0;
if (oldvc == self->cga.crtc[4]) {
self->cga.vc = 0;
self->cga.vadj = self->cga.crtc[5];
if (!self->cga.vadj)
self->cga.cgadispon = 1;
if (!self->cga.vadj)
self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff;
if ((self->cga.crtc[10] & 0x60) == 0x20)
self->cga.cursoron = 0;
else
self->cga.cursoron = self->cga.cgablink & 8;
}
if (self->cga.vc == self->cga.crtc[7]) {
self->cga.cgadispon = 0;
self->cga.displine = 0;
self->cga.vsynctime = 16;
if (self->cga.crtc[7]) {
compaq_cga_log("Lastline %i Firstline %i %i\n", self->cga.lastline,
self->cga.firstline, self->cga.lastline - self->cga.firstline);
if (self->cga.cgamode & 1)
x = (self->cga.crtc[1] << 3) + 16;
else
x = (self->cga.crtc[1] << 4) + 16;
self->cga.lastline++;
xs_temp = x;
ys_temp = (self->cga.lastline - self->cga.firstline);
if ((xs_temp > 0) && (ys_temp > 0)) {
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= 16;
if ((self->cga.cgamode & 8) && ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get())) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
if (enable_overscan)
video_blit_memtoscreen(0, self->cga.firstline - 8, xsize, (self->cga.lastline - self->cga.firstline) + 16);
else
video_blit_memtoscreen(8, self->cga.firstline, xsize, self->cga.lastline - self->cga.firstline);
}
frames++;
video_res_x = xsize;
if (enable_overscan)
xsize -= 16;
video_res_y = ysize;
if (self->cga.cgamode & 1) {
video_res_x /= 8;
video_res_y /= self->cga.crtc[9] + 1;
video_bpp = 0;
} else if (!(self->cga.cgamode & 2)) {
video_res_x /= 16;
video_res_y /= self->cga.crtc[9] + 1;
video_bpp = 0;
} else if (!(self->cga.cgamode & 16)) {
video_res_x /= 2;
video_bpp = 2;
} else
video_bpp = 1;
}
self->cga.firstline = 1000;
self->cga.lastline = 0;
self->cga.cgablink++;
self->cga.oddeven ^= 1;
}
} else {
self->cga.sc++;
self->cga.sc &= 31;
self->cga.ma = self->cga.maback;
}
if (self->cga.cgadispon)
self->cga.cgastat &= ~1;
if (self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1)))
self->cga.con = 1;
if (self->cga.cgadispon && (self->cga.cgamode & 1)) {
for (x = 0; x < (self->cga.crtc[1] << 1); x++)
self->cga.charbuffer[x] = self->cga.vram[((self->cga.ma << 1) + x) & 0x3fff];
}
}
}
void *
compaq_cga_init(const device_t *info)
{
int display_type;
compaq_cga_t *self = malloc(sizeof(compaq_cga_t));
memset(self, 0, sizeof(compaq_cga_t));
display_type = device_get_config_int("display_type");
self->cga.composite = (display_type != CGA_RGB);
self->cga.revision = device_get_config_int("composite_type");
self->cga.snow_enabled = device_get_config_int("snow_enabled");
self->cga.vram = malloc(0x4000);
cga_comp_init(self->cga.revision);
timer_add(&self->cga.timer, compaq_cga_poll, self, 1);
mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL /*self->cga.vram*/, MEM_MAPPING_EXTERNAL, self);
io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self);
if (info->local) {
for (uint16_t c = 0; c < 256; c++) {
mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16;
if (c & 8)
mdaattr[c][0][1] = 15 + 16;
else
mdaattr[c][0][1] = 7 + 16;
}
mdaattr[0x70][0][1] = 16;
mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15;
mdaattr[0xF0][0][1] = 16;
mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15;
mdaattr[0x78][0][1] = 16 + 7;
mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15;
mdaattr[0xF8][0][1] = 16 + 7;
mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15;
mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16;
mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16;
mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16;
mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16;
}
vflags = info->local;
overscan_x = overscan_y = 16;
self->cga.rgb_type = device_get_config_int("rgb_type");
cga_palette = (self->cga.rgb_type << 1);
cgapal_rebuild();
self->cga.crtc[9] = 13;
return self;
}
void
compaq_cga_close(void *priv)
{
compaq_cga_t *self = (compaq_cga_t *) priv;
free(self->cga.vram);
free(self);
}
void
compaq_cga_speed_changed(void *priv)
{
compaq_cga_t *self = (compaq_cga_t *) priv;
if (self->cga.crtc[9] == 13) /* Character height */
compaq_cga_recalctimings(self);
else
cga_recalctimings(&self->cga);
}
extern const device_config_t cga_config[];
const device_t compaq_cga_device = {
.name = "Compaq CGA",
.internal_name = "compaq_cga",
.flags = DEVICE_ISA,
.local = 0,
.init = compaq_cga_init,
.close = compaq_cga_close,
.reset = NULL,
.available = NULL,
.speed_changed = compaq_cga_speed_changed,
.force_redraw = NULL,
.config = cga_config
};
const device_t compaq_cga_2_device = {
.name = "Compaq CGA 2",
.internal_name = "compaq_cga_2",
.flags = DEVICE_ISA,
.local = 1,
.init = compaq_cga_init,
.close = compaq_cga_close,
.reset = NULL,
.available = NULL,
.speed_changed = compaq_cga_speed_changed,
.force_redraw = NULL,
.config = cga_config
};

View File

@@ -313,7 +313,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv)
if ((idx < 0xe) || (idx > 0x10)) {
if ((idx == 0xc) || (idx == 0xd)) {
ega->fullchange = 3;
ega->ma_latch = ((ega->crtc[0xc] << 8) | ega->crtc[0xd]) +
ega->memaddr_latch = ((ega->crtc[0xc] << 8) | ega->crtc[0xd]) +
((ega->crtc[8] & 0x60) >> 5);
} else {
ega->fullchange = changeframecount;
@@ -505,7 +505,7 @@ ega_in(uint16_t addr, void *priv)
case 0x3da:
ega->attrff = 0;
if (type == EGA_TYPE_COMPAQ) {
ret = ega->stat & 0xcf;
ret = ega->status & 0xcf;
switch ((ega->attrregs[0x12] >> 4) & 0x03) {
case 0x00:
/* 00 = Pri. Red (5), Pri. Blue (4) */
@@ -526,8 +526,8 @@ ega_in(uint16_t addr, void *priv)
break;
}
} else {
ega->stat ^= 0x30; /* Fools IBM EGA video BIOS self-test. */
ret = ega->stat;
ega->status ^= 0x30; /* Fools IBM EGA video BIOS self-test. */
ret = ega->status;
}
break;
case 0x7c6:
@@ -649,7 +649,7 @@ ega_recalctimings(ega_t *ega)
ega->interlace = 0;
ega->ma_latch = (ega->crtc[0xc] << 8) | ega->crtc[0xd];
ega->memaddr_latch = (ega->crtc[0xc] << 8) | ega->crtc[0xd];
ega->render = ega_render_blank;
if (!ega->scrblank && ega->attr_palette_enable) {
@@ -748,7 +748,7 @@ ega_dot_poll(void *priv)
const int dwshift = doublewidth ? 1 : 0;
const int dotwidth = 1 << dwshift;
const int charwidth = dotwidth * (seq9dot ? 9 : 8);
const int cursoron = (ega->sc == (ega->crtc[10] & 31));
const int cursoron = (ega->scanline == (ega->crtc[10] & 31));
const int cursoraddr = (ega->crtc[0xe] << 8) | ega->crtc[0xf];
uint32_t addr;
int drawcursor;
@@ -792,7 +792,7 @@ ega_dot_poll(void *priv)
else
charaddr = ega->charseta + (chr * 0x80);
dat = ega->vram[charaddr + (ega->sc << 2)];
dat = ega->vram[charaddr + (ega->scanline << 2)];
dat <<= 1;
if ((chr & ~0x1F) == 0xC0 && attrlinechars)
dat |= (dat >> 1) & 1;
@@ -837,19 +837,19 @@ ega_poll(void *priv)
if (!ega->linepos) {
timer_advance_u64(&ega->timer, ega->dispofftime);
ega->stat |= 1;
ega->status |= 1;
ega->linepos = 1;
if (ega->dispon) {
ega->hdisp_on = 1;
ega->ma &= ega->vrammask;
ega->memaddr &= ega->vrammask;
if (ega->firstline == 2000) {
ega->firstline = ega->displine;
video_wait_for_buffer();
}
old_ma = ega->ma;
old_ma = ega->memaddr;
ega->displine *= ega->vres + 1;
ega->y_add *= ega->vres + 1;
for (int y = 0; y <= ega->vres; y++) {
@@ -863,7 +863,7 @@ ega_poll(void *priv)
ega->x_add = (overscan_x >> 1) - ega->scrollcache;
if (y != ega->vres) {
ega->ma = old_ma;
ega->memaddr = old_ma;
ega->displine++;
}
}
@@ -877,8 +877,8 @@ ega_poll(void *priv)
ega->displine++;
if (ega->interlace)
ega->displine++;
if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines)
ega->stat &= ~8;
if ((ega->status & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines)
ega->status &= ~8;
ega->vslines++;
if (ega->chipset) {
if (ega->hdisp >= 800) {
@@ -896,35 +896,35 @@ ega_poll(void *priv)
timer_advance_u64(&ega->timer, ega->dispontime);
if (ega->dispon)
ega->stat &= ~1;
ega->status &= ~1;
ega->hdisp_on = 0;
ega->linepos = 0;
if ((ega->sc == (ega->crtc[11] & 31)) || (ega->sc == ega->rowcount))
ega->con = 0;
if ((ega->scanline == (ega->crtc[11] & 31)) || (ega->scanline == ega->rowcount))
ega->cursorvisible = 0;
if (ega->dispon) {
/* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll */
if (ega->linedbl && !ega->linecountff) {
ega->linecountff = 1;
ega->ma = ega->maback;
ega->cca = ega->maback;
ega->memaddr = ega->memaddr_backup;
ega->cca = ega->memaddr_backup;
}
if (ega->sc == (ega->crtc[9] & 31)) {
if (ega->scanline == (ega->crtc[9] & 31)) {
ega->linecountff = 0;
ega->sc = 0;
ega->scanline = 0;
ega->maback += (ega->rowoffset << 3);
ega->memaddr_backup += (ega->rowoffset << 3);
if (ega->interlace)
ega->maback += (ega->rowoffset << 3);
ega->maback &= ega->vrammask;
ega->ma = ega->maback;
ega->cca = ega->maback;
ega->memaddr_backup += (ega->rowoffset << 3);
ega->memaddr_backup &= ega->vrammask;
ega->memaddr = ega->memaddr_backup;
ega->cca = ega->memaddr_backup;
} else {
ega->linecountff = 0;
ega->sc++;
ega->sc &= 31;
ega->ma = ega->maback;
ega->cca = ega->maback;
ega->scanline++;
ega->scanline &= 31;
ega->memaddr = ega->memaddr_backup;
ega->cca = ega->memaddr_backup;
}
}
ega->real_vc++;
@@ -941,13 +941,13 @@ ega_poll(void *priv)
if (ega->vc == ega->split) {
// TODO: Implement the hardware bug where the first scanline is drawn twice when the split happens
if (ega->interlace && ega->oddeven)
ega->ma = ega->maback = ega->rowoffset << 1;
ega->memaddr = ega->memaddr_backup = ega->rowoffset << 1;
else
ega->ma = ega->maback = 0;
ega->ma <<= 2;
ega->cca = ega->ma;
ega->maback <<= 2;
ega->sc = 0;
ega->memaddr = ega->memaddr_backup = 0;
ega->memaddr <<= 2;
ega->cca = ega->memaddr;
ega->memaddr_backup <<= 2;
ega->scanline = 0;
}
if (ega->vc == ega->dispend) {
ega->dispon = 0;
@@ -968,7 +968,7 @@ ega_poll(void *priv)
}
if (ega->vc == ega->vsyncstart) {
ega->dispon = 0;
ega->stat |= 8;
ega->status |= 8;
#if 0
picint(1 << 2);
#endif
@@ -1007,19 +1007,19 @@ ega_poll(void *priv)
ega->vslines = 0;
if (ega->interlace && ega->oddeven)
ega->ma = ega->maback = ega->ma_latch + (ega->rowoffset << 1);
ega->memaddr = ega->memaddr_backup = ega->memaddr_latch + (ega->rowoffset << 1);
else
ega->ma = ega->maback = ega->ma_latch;
ega->ca = (ega->crtc[0xe] << 8) | ega->crtc[0xf];
ega->memaddr = ega->memaddr_backup = ega->memaddr_latch;
ega->cursoraddr = (ega->crtc[0xe] << 8) | ega->crtc[0xf];
ega->ma <<= 2;
ega->maback <<= 2;
ega->ca <<= 2;
ega->cca = ega->ma;
ega->memaddr <<= 2;
ega->memaddr_backup <<= 2;
ega->cursoraddr <<= 2;
ega->cca = ega->memaddr;
}
if (ega->vc == ega->vtotal) {
ega->vc = 0;
ega->sc = (ega->crtc[0x8] & 0x1f);
ega->scanline = (ega->crtc[0x8] & 0x1f);
ega->dispon = 1;
ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0;
@@ -1036,8 +1036,8 @@ ega_poll(void *priv)
ega->linecountff = 0;
}
if (ega->sc == (ega->crtc[10] & 31))
ega->con = 1;
if (ega->scanline == (ega->crtc[10] & 31))
ega->cursorvisible = 1;
}
}
@@ -1512,24 +1512,24 @@ ega_init(ega_t *ega, int monitor_type, int is_mono)
ega->pallook = pallook16;
for (uint16_t c = 0; c < 256; c++) {
ega->mdacols[c][0][0] = ega->mdacols[c][1][0] = ega->mdacols[c][1][1] = 16;
ega->mda_attr_to_color_table[c][0][0] = ega->mda_attr_to_color_table[c][1][0] = ega->mda_attr_to_color_table[c][1][1] = 16;
if (c & 8)
ega->mdacols[c][0][1] = 15 + 16;
ega->mda_attr_to_color_table[c][0][1] = 15 + 16;
else
ega->mdacols[c][0][1] = 7 + 16;
ega->mda_attr_to_color_table[c][0][1] = 7 + 16;
}
ega->mdacols[0x70][0][1] = 16;
ega->mdacols[0x70][0][0] = ega->mdacols[0x70][1][0] = ega->mdacols[0x70][1][1] = 16 + 15;
ega->mdacols[0xF0][0][1] = 16;
ega->mdacols[0xF0][0][0] = ega->mdacols[0xF0][1][0] = ega->mdacols[0xF0][1][1] = 16 + 15;
ega->mdacols[0x78][0][1] = 16 + 7;
ega->mdacols[0x78][0][0] = ega->mdacols[0x78][1][0] = ega->mdacols[0x78][1][1] = 16 + 15;
ega->mdacols[0xF8][0][1] = 16 + 7;
ega->mdacols[0xF8][0][0] = ega->mdacols[0xF8][1][0] = ega->mdacols[0xF8][1][1] = 16 + 15;
ega->mdacols[0x00][0][1] = ega->mdacols[0x00][1][1] = 16;
ega->mdacols[0x08][0][1] = ega->mdacols[0x08][1][1] = 16;
ega->mdacols[0x80][0][1] = ega->mdacols[0x80][1][1] = 16;
ega->mdacols[0x88][0][1] = ega->mdacols[0x88][1][1] = 16;
ega->mda_attr_to_color_table[0x70][0][1] = 16;
ega->mda_attr_to_color_table[0x70][0][0] = ega->mda_attr_to_color_table[0x70][1][0] = ega->mda_attr_to_color_table[0x70][1][1] = 16 + 15;
ega->mda_attr_to_color_table[0xF0][0][1] = 16;
ega->mda_attr_to_color_table[0xF0][0][0] = ega->mda_attr_to_color_table[0xF0][1][0] = ega->mda_attr_to_color_table[0xF0][1][1] = 16 + 15;
ega->mda_attr_to_color_table[0x78][0][1] = 16 + 7;
ega->mda_attr_to_color_table[0x78][0][0] = ega->mda_attr_to_color_table[0x78][1][0] = ega->mda_attr_to_color_table[0x78][1][1] = 16 + 15;
ega->mda_attr_to_color_table[0xF8][0][1] = 16 + 7;
ega->mda_attr_to_color_table[0xF8][0][0] = ega->mda_attr_to_color_table[0xF8][1][0] = ega->mda_attr_to_color_table[0xF8][1][1] = 16 + 15;
ega->mda_attr_to_color_table[0x00][0][1] = ega->mda_attr_to_color_table[0x00][1][1] = 16;
ega->mda_attr_to_color_table[0x08][0][1] = ega->mda_attr_to_color_table[0x08][1][1] = 16;
ega->mda_attr_to_color_table[0x80][0][1] = ega->mda_attr_to_color_table[0x80][1][1] = 16;
ega->mda_attr_to_color_table[0x88][0][1] = ega->mda_attr_to_color_table[0x88][1][1] = 16;
egaswitches = monitor_type & 0xf;

View File

@@ -141,9 +141,9 @@ ega_render_text(ega_t *ega)
}
for (int x = 0; x < (ega->hdisp + ega->scrollcache); x += charwidth) {
uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask;
uint32_t addr = ega->remap_func(ega, ega->memaddr) & ega->vrammask;
int drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
int drawcursor = ((ega->memaddr == ega->cursoraddr) && ega->cursorvisible && ega->cursoron);
uint32_t chr;
uint32_t attr;
@@ -175,7 +175,7 @@ ega_render_text(ega_t *ega)
}
}
uint32_t dat = ega->vram[charaddr + (ega->sc << 2)];
uint32_t dat = ega->vram[charaddr + (ega->scanline << 2)];
dat <<= 1;
if (((chr & ~0x1f) == 0xc0) && attrlinechars)
dat |= (dat >> 1) & 1;
@@ -184,21 +184,21 @@ ega_render_text(ega_t *ega)
if (monoattrs) {
int bit = (dat & (0x100 >> (xx >> dwshift))) ? 1 : 0;
int blink = (!drawcursor && (attr & 0x80) && attrblink && blinked);
if ((ega->sc == ega->crtc[0x14]) && ((attr & 7) == 1))
p[xx] = ega->mdacols[attr][blink][1];
if ((ega->scanline == ega->crtc[0x14]) && ((attr & 7) == 1))
p[xx] = ega->mda_attr_to_color_table[attr][blink][1];
else
p[xx] = ega->mdacols[attr][blink][bit];
p[xx] = ega->mda_attr_to_color_table[attr][blink][bit];
if (drawcursor)
p[xx] ^= ega->mdacols[attr][0][1];
p[xx] ^= ega->mda_attr_to_color_table[attr][0][1];
p[xx] = ega->pallook[ega->egapal[p[xx] & 0x0f]];
} else
p[xx] = (dat & (0x100 >> (xx >> dwshift))) ? fg : bg;
}
ega->ma += 4;
ega->memaddr += 4;
p += charwidth;
}
ega->ma &= 0x3ffff;
ega->memaddr &= 0x3ffff;
}
}
@@ -236,7 +236,7 @@ ega_render_graphics(ega_t *ega)
}
for (int x = 0; x <= (ega->hdisp + ega->scrollcache); x += charwidth) {
uint32_t addr = ega->remap_func(ega, ega->ma) & ega->vrammask;
uint32_t addr = ega->remap_func(ega, ega->memaddr) & ega->vrammask;
uint8_t edat[4];
if (seqoddeven) {
@@ -247,12 +247,12 @@ ega_render_graphics(ega_t *ega)
edat[3] = ega->vram[(addr | 3) ^ secondcclk];
secondcclk = (secondcclk + 1) & 1;
if (secondcclk == 0)
ega->ma += 4;
ega->memaddr += 4;
} else {
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&ega->vram[addr]);
ega->ma += 4;
ega->memaddr += 4;
}
ega->ma &= 0x3ffff;
ega->memaddr &= 0x3ffff;
if (cga2bpp) {
// Remap CGA 2bpp-chunky data into fully planar data

View File

@@ -424,7 +424,7 @@ et3000_out(uint16_t addr, uint8_t val, void *priv)
static void
et3000_recalctimings(svga_t *svga)
{
svga->ma_latch |= (svga->crtc[0x23] & 2) << 15;
svga->memaddr_latch |= (svga->crtc[0x23] & 2) << 15;
if (svga->crtc[0x25] & 1)
svga->vblankstart |= 0x400;
if (svga->crtc[0x25] & 2)
@@ -439,7 +439,7 @@ et3000_recalctimings(svga_t *svga)
svga->interlace = !!(svga->crtc[0x25] & 0x80);
if (svga->attrregs[0x16] & 0x10) {
svga->ma_latch <<= (1 << 0);
svga->memaddr_latch <<= (1 << 0);
svga->rowoffset <<= (1 << 0);
switch (svga->gdcreg[5] & 0x60) {
case 0x00:

View File

@@ -378,7 +378,7 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
@@ -642,7 +642,7 @@ et4000_recalctimings(svga_t *svga)
{
const et4000_t *dev = (et4000_t *) svga->priv;
svga->ma_latch |= (svga->crtc[0x33] & 3) << 16;
svga->memaddr_latch |= (svga->crtc[0x33] & 3) << 16;
svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2];
@@ -701,7 +701,7 @@ et4000_recalctimings(svga_t *svga)
if (dev->type == ET4000_TYPE_KOREAN || dev->type == ET4000_TYPE_TRIGEM || dev->type == ET4000_TYPE_KASAN) {
if ((svga->render == svga_render_text_80) && ((svga->crtc[0x37] & 0x0A) == 0x0A)) {
if (dev->port_32cb_val & 0x80) {
svga->ma_latch -= 2;
svga->memaddr_latch -= 2;
svga->ca_adj = -2;
}
if ((dev->port_32cb_val & 0xB4) == ((svga->crtc[0x37] & 3) == 2 ? 0xB4 : 0xB0)) {
@@ -719,7 +719,7 @@ et4000_recalctimings(svga_t *svga)
}
if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40) && svga->lowres) {
svga->ma_latch <<= 1;
svga->memaddr_latch <<= 1;
svga->rowoffset <<= 1;
svga->render = svga_render_8bpp_highres;
}
@@ -734,7 +734,7 @@ et4000_kasan_recalctimings(svga_t *svga)
if (svga->render == svga_render_text_80 && (et4000->kasan_cfg_regs[0] & 8)) {
svga->hdisp += svga->dots_per_clock;
svga->ma_latch -= 4;
svga->memaddr_latch -= 4;
svga->ca_adj = (et4000->kasan_cfg_regs[0] >> 6) - 3;
svga->ksc5601_sbyte_mask = (et4000->kasan_cfg_regs[0] & 4) << 5;
if ((et4000->kasan_cfg_regs[0] & 0x23) == 0x20 && (et4000->kasan_cfg_regs[4] & 0x80) && ((svga->crtc[0x37] & 0x0B) == 0x0A))

View File

@@ -238,7 +238,7 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
@@ -430,7 +430,7 @@ et4000w32p_recalctimings(svga_t *svga)
{
et4000w32p_t *et4000 = (et4000w32p_t *) svga->priv;
svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16;
svga->memaddr_latch |= (svga->crtc[0x33] & 0x7) << 16;
svga->hblankstart = (((svga->crtc[0x3f] & 0x4) >> 2) << 8) + svga->crtc[2];

View File

@@ -361,28 +361,28 @@ f82c425_text_row(f82c425_t *f82c425)
int cursorline;
int blink;
uint16_t addr;
uint8_t sc;
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
uint16_t ca = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff;
uint8_t sl = f82c425->cga.crtc[9] + 1;
int columns = f82c425->cga.crtc[1];
uint8_t scanline;
uint16_t memaddr = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
uint16_t cursoraddr = (f82c425->cga.crtc[0x0f] | (f82c425->cga.crtc[0x0e] << 8)) & 0x3fff;
uint8_t sl = f82c425->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1;
int columns = f82c425->cga.crtc[CGA_CRTC_HDISP];
sc = (f82c425->displine) & 7;
addr = ((ma & ~1) + (f82c425->displine >> 3) * columns) * 2;
ma += (f82c425->displine >> 3) * columns;
scanline = (f82c425->displine) & 7;
addr = ((memaddr & ~1) + (f82c425->displine >> 3) * columns) * 2;
memaddr += (f82c425->displine >> 3) * columns;
if ((f82c425->cga.crtc[0x0a] & 0x60) == 0x20) {
if ((f82c425->cga.crtc[CGA_CRTC_CURSOR_START] & 0x60) == 0x20) {
cursorline = 0;
} else {
cursorline = ((f82c425->cga.crtc[0x0a] & 0x0F) <= sc) && ((f82c425->cga.crtc[0x0b] & 0x0F) >= sc);
cursorline = ((f82c425->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0F) <= scanline) && ((f82c425->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= scanline);
}
for (int x = 0; x < columns; x++) {
chr = f82c425->vram[(addr + 2 * x) & 0x3FFF];
attr = f82c425->vram[(addr + 2 * x + 1) & 0x3FFF];
drawcursor = ((ma == ca) && cursorline && (f82c425->cga.cgamode & 0x8) && (f82c425->cga.cgablink & 0x10));
drawcursor = ((memaddr == cursoraddr) && cursorline && (f82c425->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) && (f82c425->cga.cgablink & 0x10));
blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor);
blink = ((f82c425->cga.cgablink & 0x10) && (f82c425->cga.cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
if (drawcursor) {
colors[0] = smartmap[~attr & 0xff][0];
@@ -398,16 +398,16 @@ f82c425_text_row(f82c425_t *f82c425)
if (f82c425->cga.cgamode & 0x01) {
/* High resolution (80 cols) */
for (c = 0; c < sl; c++) {
(buffer32->line[f82c425->displine])[(x << 3) + c] = colors[(fontdat[chr][sc] & (1 << (c ^ 7))) ? 1 : 0];
(buffer32->line[f82c425->displine])[(x << 3) + c] = colors[(fontdat[chr][scanline] & (1 << (c ^ 7))) ? 1 : 0];
}
} else {
/* Low resolution (40 columns, stretch pixels horizontally) */
for (c = 0; c < sl; c++) {
(buffer32->line[f82c425->displine])[(x << 4) + c * 2] = (buffer32->line[f82c425->displine])[(x << 4) + c * 2 + 1] = colors[(fontdat[chr][sc] & (1 << (c ^ 7))) ? 1 : 0];
(buffer32->line[f82c425->displine])[(x << 4) + c * 2] = (buffer32->line[f82c425->displine])[(x << 4) + c * 2 + 1] = colors[(fontdat[chr][scanline] & (1 << (c ^ 7))) ? 1 : 0];
}
}
++ma;
++memaddr;
}
}
@@ -418,9 +418,9 @@ f82c425_cgaline6(f82c425_t *f82c425)
uint8_t dat;
uint16_t addr;
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
uint16_t memaddr = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((ma & ~1) << 1);
addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((memaddr & ~1) << 1);
for (uint8_t x = 0; x < 80; x++) {
dat = f82c425->vram[addr & 0x3FFF];
@@ -442,8 +442,8 @@ f82c425_cgaline4(f82c425_t *f82c425)
uint8_t pattern;
uint16_t addr;
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((ma & ~1) << 1);
uint16_t memaddr = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
addr = ((f82c425->displine) & 1) * 0x2000 + (f82c425->displine >> 1) * 80 + ((memaddr & ~1) << 1);
for (uint8_t x = 0; x < 80; x++) {
dat = f82c425->vram[addr & 0x3FFF];
@@ -526,7 +526,7 @@ f82c425_poll(void *priv)
f82c425->displine = 0;
f82c425->cga.cgastat &= ~8;
f82c425->dispon = 1;
} else if (f82c425->displine == (f82c425->cga.crtc[9] + 1) * f82c425->cga.crtc[6]) {
} else if (f82c425->displine == (f82c425->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] + 1) * f82c425->cga.crtc[CGA_CRTC_VDISP]) {
/* Start of VSYNC */
f82c425->cga.cgastat |= 8;
f82c425->dispon = 0;

View File

@@ -387,7 +387,7 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80)
int cw = 9; /* Each character is 9 pixels wide */
uint8_t chr;
uint8_t attr;
uint8_t sc;
uint8_t scanline;
uint8_t ctrl;
const uint8_t *crtc;
uint8_t bitmap[2];
@@ -398,8 +398,8 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80)
int drawcursor;
int cursorline;
uint16_t addr;
uint16_t ma = (genius->mda_crtc[13] | (genius->mda_crtc[12] << 8)) & 0x3fff;
uint16_t ca = (genius->mda_crtc[15] | (genius->mda_crtc[14] << 8)) & 0x3fff;
uint16_t memaddr = (genius->mda_crtc[13] | (genius->mda_crtc[12] << 8)) & 0x3fff;
uint16_t cursoraddr = (genius->mda_crtc[15] | (genius->mda_crtc[14] << 8)) & 0x3fff;
const uint8_t *framebuf = genius->vram + 0x10000;
uint32_t col;
uint32_t dl = genius->displine;
@@ -416,14 +416,14 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80)
#if 0
if (genius->genius_charh & 0x10) {
row = ((dl >> 1) / charh);
sc = ((dl >> 1) % charh);
scanline = ((dl >> 1) % charh);
} else {
row = (dl / charh);
sc = (dl % charh);
scanline = (dl % charh);
}
#else
row = (dl / charh);
sc = (dl % charh);
scanline = (dl % charh);
#endif
} else {
if ((genius->displine < 512) || (genius->displine >= 912))
@@ -439,23 +439,23 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80)
charh = crtc[9] + 1;
row = ((dl >> 1) / charh);
sc = ((dl >> 1) % charh);
scanline = ((dl >> 1) % charh);
}
ma = (crtc[13] | (crtc[12] << 8)) & 0x3fff;
ca = (crtc[15] | (crtc[14] << 8)) & 0x3fff;
memaddr = (crtc[13] | (crtc[12] << 8)) & 0x3fff;
cursoraddr = (crtc[15] | (crtc[14] << 8)) & 0x3fff;
addr = ((ma & ~1) + row * w) * 2;
addr = ((memaddr & ~1) + row * w) * 2;
if (!mda)
dl += 512;
ma += (row * w);
memaddr += (row * w);
if ((crtc[10] & 0x60) == 0x20)
cursorline = 0;
else
cursorline = ((crtc[10] & 0x1F) <= sc) && ((crtc[11] & 0x1F) >= sc);
cursorline = ((crtc[10] & 0x1F) <= scanline) && ((crtc[11] & 0x1F) >= scanline);
for (int x = 0; x < w; x++) {
#if 0
@@ -467,7 +467,7 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80)
chr = framebuf[(addr + 2 * x) & 0x3FFF];
attr = framebuf[(addr + 2 * x + 1) & 0x3FFF];
drawcursor = ((ma == ca) && cursorline && genius->enabled && (ctrl & 8));
drawcursor = ((memaddr == cursoraddr) && cursorline && genius->enabled && (ctrl & 8));
switch (crtc[10] & 0x60) {
case 0x00:
@@ -487,7 +487,7 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80)
attr &= 0x7F;
/* MDA underline */
if (mda && (sc == charh) && ((attr & 7) == 1)) {
if (mda && (scanline == charh) && ((attr & 7) == 1)) {
col = mdaattr[attr][blink][1];
if (genius->genius_control & 0x20)
@@ -504,9 +504,9 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80)
}
} else { /* Draw 8 pixels of character */
if (mda)
bitmap[0] = fontdat8x12[chr][sc];
bitmap[0] = fontdat8x12[chr][scanline];
else
bitmap[0] = fontdat[chr][sc];
bitmap[0] = fontdat[chr][scanline];
for (c = 0; c < 8; c++) {
col = mdaattr[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0];
@@ -563,7 +563,7 @@ genius_textline(genius_t *genius, uint8_t background, int mda, int cols80)
}
}
}
++ma;
++memaddr;
}
}
}

View File

@@ -168,9 +168,9 @@ hercules_in(uint16_t addr, void *priv)
case 0x03b5:
case 0x03b7:
if (dev->crtcreg == 0x0c)
ret = (dev->ma >> 8) & 0x3f;
ret = (dev->memaddr >> 8) & 0x3f;
else if (dev->crtcreg == 0x0d)
ret = dev->ma & 0xff;
ret = dev->memaddr & 0xff;
else
ret = dev->crtc[dev->crtcreg];
break;
@@ -178,8 +178,8 @@ hercules_in(uint16_t addr, void *priv)
case 0x03ba:
ret = 0x70; /* Hercules ident */
ret |= (dev->lp_ff ? 2 : 0);
ret |= (dev->stat & 0x01);
if (dev->stat & 0x08)
ret |= (dev->status & 0x01);
if (dev->status & 0x08)
ret |= 0x80;
if ((ret & 0x81) == 0x80)
ret |= 0x08;
@@ -281,10 +281,10 @@ hercules_poll(void *priv)
hercules_t *dev = (hercules_t *) priv;
uint8_t chr;
uint8_t attr;
uint16_t ca;
uint16_t cursoraddr;
uint16_t dat;
uint16_t pa;
int oldsc;
int scanline_old;
int blink;
int x;
int xx;
@@ -296,16 +296,16 @@ hercules_poll(void *priv)
uint32_t *p;
VIDEO_MONITOR_PROLOGUE()
ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
cursoraddr = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
if (!dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->stat |= 1;
dev->status |= 1;
dev->linepos = 1;
oldsc = dev->sc;
scanline_old = dev->scanline;
if ((dev->crtc[8] & 3) == 3)
dev->sc = (dev->sc << 1) & 7;
dev->scanline = (dev->scanline << 1) & 7;
if (dev->dispon) {
if (dev->displine < dev->firstline) {
@@ -317,16 +317,16 @@ hercules_poll(void *priv)
hercules_render_overscan_left(dev);
if (dev->ctrl & 0x02) {
ca = (dev->sc & 3) * 0x2000;
cursoraddr = (dev->scanline & 3) * 0x2000;
if (dev->ctrl & 0x80)
ca += 0x8000;
cursoraddr += 0x8000;
for (x = 0; x < dev->crtc[1]; x++) {
if (dev->ctrl & 8)
dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1];
dat = (dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr] << 8) | dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 1];
else
dat = 0;
dev->ma++;
dev->memaddr++;
for (c = 0; c < 16; c++)
buffer32->line[dev->displine + 14][(x << 4) + c + 8] = (dat & (32768 >> c)) ? 7 : 0;
for (c = 0; c < 16; c += 8)
@@ -341,25 +341,25 @@ hercules_poll(void *priv)
attr = dev->charbuffer[(x << 1) + 1];
} else
chr = attr = 0;
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron);
blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
if (dev->sc == 12 && ((attr & 7) == 1)) {
if (dev->scanline == 12 && ((attr & 7) == 1)) {
for (c = 0; c < 9; c++)
buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][1];
} else {
for (c = 0; c < 8; c++)
buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0];
buffer32->line[dev->displine + 14][(x * 9) + c + 8] = dev->cols[attr][blink][(fontdatm[chr][dev->scanline] & (1 << (c ^ 7))) ? 1 : 0];
if ((chr & ~0x1f) == 0xc0)
buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1];
buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][fontdatm[chr][dev->scanline] & 1];
else
buffer32->line[dev->displine + 14][(x * 9) + 8 + 8] = dev->cols[attr][blink][0];
}
if (dev->ctrl2 & 0x01)
dev->ma = (dev->ma + 1) & 0x3fff;
dev->memaddr = (dev->memaddr + 1) & 0x3fff;
else
dev->ma = (dev->ma + 1) & 0x7ff;
dev->memaddr = (dev->memaddr + 1) & 0x7ff;
if (drawcursor) {
for (c = 0; c < 9; c++)
@@ -377,10 +377,10 @@ hercules_poll(void *priv)
video_process_8(x + 16, dev->displine + 14);
}
dev->sc = oldsc;
dev->scanline = scanline_old;
if (dev->vc == dev->crtc[7] && !dev->sc)
dev->stat |= 8;
if (dev->vc == dev->crtc[7] && !dev->scanline)
dev->status |= 8;
dev->displine++;
if (dev->displine >= 500)
dev->displine = 0;
@@ -388,33 +388,32 @@ hercules_poll(void *priv)
timer_advance_u64(&dev->timer, dev->dispontime);
if (dev->dispon)
dev->stat &= ~1;
dev->status &= ~1;
dev->linepos = 0;
if (dev->vsynctime) {
dev->vsynctime--;
if (!dev->vsynctime)
dev->stat &= ~8;
dev->status &= ~8;
}
if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
dev->con = 0;
dev->coff = 1;
if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) {
dev->cursorvisible = 0;
}
if (dev->vadj) {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
dev->scanline++;
dev->scanline &= 31;
dev->memaddr = dev->memaddr_backup;
dev->vadj--;
if (!dev->vadj) {
dev->dispon = 1;
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->sc = 0;
dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->scanline = 0;
}
} else if (((dev->crtc[8] & 3) != 3 && dev->sc == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) {
dev->maback = dev->ma;
dev->sc = 0;
} else if (((dev->crtc[8] & 3) != 3 && dev->scanline == dev->crtc[9]) || ((dev->crtc[8] & 3) == 3 && dev->scanline == (dev->crtc[9] >> 1))) {
dev->memaddr_backup = dev->memaddr;
dev->scanline = 0;
oldvc = dev->vc;
dev->vc++;
dev->vc &= 127;
@@ -427,7 +426,7 @@ hercules_poll(void *priv)
dev->vadj = dev->crtc[5];
if (!dev->vadj) {
dev->dispon = 1;
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
}
switch (dev->crtc[10] & 0x60) {
case 0x20:
@@ -512,17 +511,17 @@ hercules_poll(void *priv)
dev->blink++;
}
} else {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
dev->scanline++;
dev->scanline &= 31;
dev->memaddr = dev->memaddr_backup;
}
if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))
dev->con = 1;
if (dev->scanline == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[10] & 31) >> 1)))
dev->cursorvisible = 1;
if (dev->dispon && !(dev->ctrl & 0x02)) {
for (x = 0; x < (dev->crtc[1] << 1); x++) {
pa = (dev->ctrl & 0x80) ? ((x & 1) ? 0x0000 : 0x8000) : 0x0000;
dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff) + pa];
dev->charbuffer[x] = dev->vram[(((dev->memaddr << 1) + x) & 0x3fff) + pa];
}
}
}

View File

@@ -157,7 +157,7 @@ typedef struct {
uint8_t crtc[32];
int crtcreg;
uint8_t ctrl, ctrl2, stat;
uint8_t ctrl, ctrl2, status;
uint64_t dispontime, dispofftime;
pc_timer_t timer;
@@ -165,9 +165,9 @@ typedef struct {
int firstline, lastline;
int linepos, displine;
int vc, sc;
uint16_t ma, maback;
int con, coff, cursoron;
int vc, scanline;
uint16_t memaddr, memaddr_backup;
int cursorvisible, cursoron;
int dispon, blink;
int vsynctime;
int vadj;
@@ -285,7 +285,7 @@ incolor_in(uint16_t port, void *priv)
case 0x3ba:
/* 0x50: InColor card identity */
ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x50;
ret = (dev->status & 0xf) | ((dev->status & 8) << 4) | 0x50;
break;
default:
@@ -483,11 +483,11 @@ draw_char_rom(incolor_t *dev, int x, uint8_t chr, uint8_t attr)
elg = ((chr >= 0xc0) && (chr <= 0xdf));
}
fnt = &(fontdatm[chr][dev->sc]);
fnt = &(fontdatm[chr][dev->scanline]);
if (blk) {
val = 0x000; /* Blinking, draw all background */
} else if (dev->sc == ull) {
} else if (dev->scanline == ull) {
val = 0x1ff; /* Underscore, draw all foreground */
} else {
val = fnt[0] << 1;
@@ -559,12 +559,12 @@ draw_char_ram4(incolor_t *dev, int x, uint8_t chr, uint8_t attr)
} else {
elg = ((chr >= 0xc0) && (chr <= 0xdf));
}
fnt = dev->vram + 0x4000 + 16 * chr + dev->sc;
fnt = dev->vram + 0x4000 + 16 * chr + dev->scanline;
if (blk) {
/* Blinking, draw all background */
val[0] = val[1] = val[2] = val[3] = 0x000;
} else if (dev->sc == ull) {
} else if (dev->scanline == ull) {
/* Underscore, draw all foreground */
val[0] = val[1] = val[2] = val[3] = 0x1ff;
} else {
@@ -685,12 +685,12 @@ draw_char_ram48(incolor_t *dev, int x, uint8_t chr, uint8_t attr)
} else {
elg = ((chr >= 0xc0) && (chr <= 0xdf));
}
fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc;
fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->scanline;
if (blk) {
/* Blinking, draw all background */
val[0] = val[1] = val[2] = val[3] = 0x000;
} else if (dev->sc == ull) {
} else if (dev->scanline == ull) {
/* Underscore, draw all foreground */
val[0] = val[1] = val[2] = val[3] = 0x1ff;
} else {
@@ -716,9 +716,9 @@ draw_char_ram48(incolor_t *dev, int x, uint8_t chr, uint8_t attr)
/* Generate pixel colour */
cfg = 0;
pmask = 1;
if (dev->sc == oll) {
if (dev->scanline == oll) {
cfg = olc ^ ibg; /* Strikethrough */
} else if (dev->sc == ull) {
} else if (dev->scanline == ull) {
cfg = ulc ^ ibg; /* Underline */
} else {
for (uint8_t plane = 0; plane < 4; plane++, pmask = pmask << 1) {
@@ -746,7 +746,7 @@ draw_char_ram48(incolor_t *dev, int x, uint8_t chr, uint8_t attr)
}
static void
text_line(incolor_t *dev, uint16_t ca)
text_line(incolor_t *dev, uint16_t cursoraddr)
{
int drawcursor;
uint8_t chr;
@@ -755,12 +755,12 @@ text_line(incolor_t *dev, uint16_t ca)
for (uint8_t x = 0; x < dev->crtc[1]; x++) {
if (dev->ctrl & 8) {
chr = dev->vram[(dev->ma << 1) & 0x3fff];
attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff];
chr = dev->vram[(dev->memaddr << 1) & 0x3fff];
attr = dev->vram[((dev->memaddr << 1) + 1) & 0x3fff];
} else
chr = attr = 0;
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron);
switch (dev->crtc[INCOLOR_CRTC_XMODE] & 5) {
case 0:
@@ -779,7 +779,7 @@ text_line(incolor_t *dev, uint16_t ca)
default:
break;
}
++dev->ma;
++dev->memaddr;
if (drawcursor) {
int cw = INCOLOR_CW;
@@ -808,29 +808,29 @@ static void
graphics_line(incolor_t *dev)
{
uint8_t mask;
uint16_t ca;
uint16_t cursoraddr;
int plane;
int col;
uint8_t ink;
uint16_t val[4];
/* Graphics mode. */
ca = (dev->sc & 3) * 0x2000;
cursoraddr = (dev->scanline & 3) * 0x2000;
if ((dev->ctrl & INCOLOR_CTRL_PAGE1) && (dev->ctrl2 & INCOLOR_CTRL2_PAGE1))
ca += 0x8000;
cursoraddr += 0x8000;
for (uint8_t x = 0; x < dev->crtc[1]; x++) {
mask = dev->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */
for (plane = 0; plane < 4; plane++, mask = mask >> 1) {
if (dev->ctrl & 8) {
if (mask & 1)
val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1];
val[plane] = (dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 0x10000 * plane] << 8) | dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 0x10000 * plane + 1];
else
val[plane] = 0;
} else
val[plane] = 0;
}
dev->ma++;
dev->memaddr++;
for (uint8_t c = 0; c < 16; c++) {
ink = 0;
@@ -855,19 +855,19 @@ static void
incolor_poll(void *priv)
{
incolor_t *dev = (incolor_t *) priv;
uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
int x;
int oldvc;
int oldsc;
int scanline_old;
int cw = INCOLOR_CW;
if (!dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->stat |= 1;
dev->status |= 1;
dev->linepos = 1;
oldsc = dev->sc;
scanline_old = dev->scanline;
if ((dev->crtc[8] & 3) == 3)
dev->sc = (dev->sc << 1) & 7;
dev->scanline = (dev->scanline << 1) & 7;
if (dev->dispon) {
if (dev->displine < dev->firstline) {
@@ -878,44 +878,43 @@ incolor_poll(void *priv)
if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH))
graphics_line(dev);
else
text_line(dev, ca);
text_line(dev, cursoraddr);
}
dev->sc = oldsc;
if (dev->vc == dev->crtc[7] && !dev->sc)
dev->stat |= 8;
dev->scanline = scanline_old;
if (dev->vc == dev->crtc[7] && !dev->scanline)
dev->status |= 8;
dev->displine++;
if (dev->displine >= 500)
dev->displine = 0;
} else {
timer_advance_u64(&dev->timer, dev->dispontime);
if (dev->dispon)
dev->stat &= ~1;
dev->status &= ~1;
dev->linepos = 0;
if (dev->vsynctime) {
dev->vsynctime--;
if (!dev->vsynctime)
dev->stat &= ~8;
dev->status &= ~8;
}
if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
dev->con = 0;
dev->coff = 1;
if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) {
dev->cursorvisible = 0;
}
if (dev->vadj) {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
dev->scanline++;
dev->scanline &= 31;
dev->memaddr = dev->memaddr_backup;
dev->vadj--;
if (!dev->vadj) {
dev->dispon = 1;
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->sc = 0;
dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->scanline = 0;
}
} else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) {
dev->maback = dev->ma;
dev->sc = 0;
oldvc = dev->vc;
} else if (dev->scanline == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->scanline == (dev->crtc[9] >> 1))) {
dev->memaddr_backup = dev->memaddr;
dev->scanline = 0;
oldvc = dev->vc;
dev->vc++;
dev->vc &= 127;
if (dev->vc == dev->crtc[6])
@@ -926,7 +925,7 @@ incolor_poll(void *priv)
if (!dev->vadj)
dev->dispon = 1;
if (!dev->vadj)
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
if ((dev->crtc[10] & 0x60) == 0x20)
dev->cursoron = 0;
else
@@ -972,13 +971,13 @@ incolor_poll(void *priv)
dev->blink++;
}
} else {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
dev->scanline++;
dev->scanline &= 31;
dev->memaddr = dev->memaddr_backup;
}
if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))
dev->con = 1;
if (dev->scanline == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[10] & 31) >> 1)))
dev->cursorvisible = 1;
}
}

View File

@@ -67,7 +67,7 @@ typedef struct {
uint8_t crtc[32];
int crtcreg;
uint8_t ctrl, ctrl2, stat;
uint8_t ctrl, ctrl2, status;
uint64_t dispontime, dispofftime;
pc_timer_t timer;
@@ -75,9 +75,9 @@ typedef struct {
int firstline, lastline;
int linepos, displine;
int vc, sc;
uint16_t ma, maback;
int con, coff, cursoron;
int vc, scanline;
uint16_t memaddr, memaddr_backup;
int cursorvisible, cursoron;
int dispon, blink;
int vsynctime;
int vadj;
@@ -194,7 +194,7 @@ herculesplus_in(uint16_t port, void *priv)
case 0x3ba:
/* 0x10: Hercules Plus card identity */
ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10;
ret = (dev->status & 0xf) | ((dev->status & 8) << 4) | 0x10;
break;
default:
@@ -260,11 +260,11 @@ draw_char_rom(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr)
else
elg = ((chr >= 0xc0) && (chr <= 0xdf));
fnt = &(fontdatm[chr][dev->sc]);
fnt = &(fontdatm[chr][dev->scanline]);
if (blk) {
val = 0x000; /* Blinking, draw all background */
} else if (dev->sc == ull) {
} else if (dev->scanline == ull) {
val = 0x1ff; /* Underscore, draw all foreground */
} else {
val = fnt[0] << 1;
@@ -319,11 +319,11 @@ draw_char_ram4(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr)
else
elg = ((chr >= 0xc0) && (chr <= 0xdf));
fnt = dev->vram + 0x4000 + 16 * chr + dev->sc;
fnt = dev->vram + 0x4000 + 16 * chr + dev->scanline;
if (blk) {
val = 0x000; /* Blinking, draw all background */
} else if (dev->sc == ull) {
} else if (dev->scanline == ull) {
val = 0x1ff; /* Underscore, draw all foreground */
} else {
val = fnt[0] << 1;
@@ -384,11 +384,11 @@ draw_char_ram48(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr)
else
elg = ((chr >= 0xc0) && (chr <= 0xdf));
fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc;
fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->scanline;
if (blk) {
val = 0x000; /* Blinking, draw all background */
} else if (dev->sc == ull) {
} else if (dev->scanline == ull) {
val = 0x1ff; /* Underscore, draw all foreground */
} else {
val = fnt[0] << 1;
@@ -404,7 +404,7 @@ draw_char_ram48(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr)
}
static void
text_line(herculesplus_t *dev, uint16_t ca)
text_line(herculesplus_t *dev, uint16_t cursoraddr)
{
int drawcursor;
uint8_t chr;
@@ -413,12 +413,12 @@ text_line(herculesplus_t *dev, uint16_t ca)
for (uint8_t x = 0; x < dev->crtc[1]; x++) {
if (dev->ctrl & 8) {
chr = dev->vram[(dev->ma << 1) & 0x3fff];
attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff];
chr = dev->vram[(dev->memaddr << 1) & 0x3fff];
attr = dev->vram[((dev->memaddr << 1) + 1) & 0x3fff];
} else
chr = attr = 0;
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
drawcursor = ((dev->memaddr == cursoraddr) && dev->cursorvisible && dev->cursoron);
switch (dev->crtc[HERCULESPLUS_CRTC_XMODE] & 5) {
case 0:
@@ -437,7 +437,7 @@ text_line(herculesplus_t *dev, uint16_t ca)
default:
break;
}
++dev->ma;
++dev->memaddr;
if (drawcursor) {
int cw = HERCULESPLUS_CW;
@@ -452,24 +452,24 @@ text_line(herculesplus_t *dev, uint16_t ca)
static void
graphics_line(herculesplus_t *dev)
{
uint16_t ca;
uint16_t cursoraddr;
int c;
int plane = 0;
uint16_t val;
/* Graphics mode. */
ca = (dev->sc & 3) * 0x2000;
cursoraddr = (dev->scanline & 3) * 0x2000;
if ((dev->ctrl & HERCULESPLUS_CTRL_PAGE1) && (dev->ctrl2 & HERCULESPLUS_CTRL2_PAGE1))
ca += 0x8000;
cursoraddr += 0x8000;
for (uint8_t x = 0; x < dev->crtc[1]; x++) {
if (dev->ctrl & 8)
val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8)
| dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1];
val = (dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 0x10000 * plane] << 8)
| dev->vram[((dev->memaddr << 1) & 0x1fff) + cursoraddr + 0x10000 * plane + 1];
else
val = 0;
dev->ma++;
dev->memaddr++;
for (c = 0; c < 16; c++) {
buffer32->line[dev->displine][(x << 4) + c] = (val & 0x8000) ? 7 : 0;
@@ -485,20 +485,20 @@ static void
herculesplus_poll(void *priv)
{
herculesplus_t *dev = (herculesplus_t *) priv;
uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
uint16_t cursoraddr = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
int x;
int oldvc;
int oldsc;
int scanline_old;
int cw = HERCULESPLUS_CW;
VIDEO_MONITOR_PROLOGUE();
if (!dev->linepos) {
timer_advance_u64(&dev->timer, dev->dispofftime);
dev->stat |= 1;
dev->status |= 1;
dev->linepos = 1;
oldsc = dev->sc;
scanline_old = dev->scanline;
if ((dev->crtc[8] & 3) == 3)
dev->sc = (dev->sc << 1) & 7;
dev->scanline = (dev->scanline << 1) & 7;
if (dev->dispon) {
if (dev->displine < dev->firstline) {
dev->firstline = dev->displine;
@@ -508,7 +508,7 @@ herculesplus_poll(void *priv)
if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH))
graphics_line(dev);
else
text_line(dev, ca);
text_line(dev, cursoraddr);
if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH))
x = dev->crtc[1] << 4;
@@ -517,40 +517,39 @@ herculesplus_poll(void *priv)
video_process_8(x, dev->displine);
}
dev->sc = oldsc;
if (dev->vc == dev->crtc[7] && !dev->sc)
dev->stat |= 8;
dev->scanline = scanline_old;
if (dev->vc == dev->crtc[7] && !dev->scanline)
dev->status |= 8;
dev->displine++;
if (dev->displine >= 500)
dev->displine = 0;
} else {
timer_advance_u64(&dev->timer, dev->dispontime);
if (dev->dispon)
dev->stat &= ~1;
dev->status &= ~1;
dev->linepos = 0;
if (dev->vsynctime) {
dev->vsynctime--;
if (!dev->vsynctime)
dev->stat &= ~8;
dev->status &= ~8;
}
if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
dev->con = 0;
dev->coff = 1;
if (dev->scanline == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[11] & 31) >> 1))) {
dev->cursorvisible = 0;
}
if (dev->vadj) {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
dev->scanline++;
dev->scanline &= 31;
dev->memaddr = dev->memaddr_backup;
dev->vadj--;
if (!dev->vadj) {
dev->dispon = 1;
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->sc = 0;
dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->scanline = 0;
}
} else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) {
dev->maback = dev->ma;
dev->sc = 0;
} else if (dev->scanline == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->scanline == (dev->crtc[9] >> 1))) {
dev->memaddr_backup = dev->memaddr;
dev->scanline = 0;
oldvc = dev->vc;
dev->vc++;
dev->vc &= 127;
@@ -562,7 +561,7 @@ herculesplus_poll(void *priv)
if (!dev->vadj)
dev->dispon = 1;
if (!dev->vadj)
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
dev->memaddr = dev->memaddr_backup = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
if ((dev->crtc[10] & 0x60) == 0x20)
dev->cursoron = 0;
else
@@ -607,13 +606,13 @@ herculesplus_poll(void *priv)
dev->blink++;
}
} else {
dev->sc++;
dev->sc &= 31;
dev->ma = dev->maback;
dev->scanline++;
dev->scanline &= 31;
dev->memaddr = dev->memaddr_backup;
}
if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))
dev->con = 1;
if (dev->scanline == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->scanline == ((dev->crtc[10] & 31) >> 1)))
dev->cursorvisible = 1;
}
VIDEO_MONITOR_EPILOGUE();

View File

@@ -448,7 +448,7 @@ ht216_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
@@ -660,10 +660,10 @@ ht216_recalctimings(svga_t *svga)
break;
}
svga->ma_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12);
svga->memaddr_latch |= ((ht216->ht_regs[0xf6] & 0x30) << 12);
if (ht216->ht_regs[0xf6] & 0x80)
svga->ma_latch = ((ht216->ht_regs[0xf6] & 0x30) << 12);
svga->memaddr_latch = ((ht216->ht_regs[0xf6] & 0x30) << 12);
svga->interlace = ht216->ht_regs[0xe0] & 0x01;

View File

@@ -113,10 +113,10 @@ typedef struct jega_t {
uint8_t attr_palette_enable;
uint32_t *pallook;
int is_vga;
int con;
int cursorvisible;
int cursoron;
int cursorblink_disable;
int ca;
int cursoraddr;
int font_index;
int sbcsbank_inv;
int attr3_sbcsbank;
@@ -222,14 +222,14 @@ jega_render_text(void *priv)
&jega->ega.x_add;
int * y_add = jega->is_vga ? &jega->vga.svga.y_add :
&jega->ega.y_add;
int * sc = jega->is_vga ? &jega->vga.svga.sc :
&jega->ega.sc;
int * sc = jega->is_vga ? &jega->vga.svga.scanline :
&jega->ega.scanline;
int * hdisp = jega->is_vga ? &jega->vga.svga.hdisp :
&jega->ega.hdisp;
int * scrollcache = jega->is_vga ? &jega->vga.svga.scrollcache :
&jega->ega.scrollcache;
uint32_t *ma = jega->is_vga ? &jega->vga.svga.ma :
&jega->ega.ma;
uint32_t *memaddr = jega->is_vga ? &jega->vga.svga.memaddr :
&jega->ega.memaddr;
uint8_t mask = jega->is_vga ? jega->vga.svga.dac_mask : 0xff;
if (*firstline_draw == 2000)
@@ -260,12 +260,12 @@ jega_render_text(void *priv)
if (jega->is_vga) {
if (!jega->vga.svga.force_old_addr)
addr = jega->vga.svga.remap_func(&jega->vga.svga, jega->vga.svga.ma) &
addr = jega->vga.svga.remap_func(&jega->vga.svga, jega->vga.svga.memaddr) &
jega->vga.svga.vram_display_mask;
} else
addr = jega->ega.remap_func(&jega->ega, *ma) & jega->ega.vrammask;
addr = jega->ega.remap_func(&jega->ega, *memaddr) & jega->ega.vrammask;
int drawcursor = ((*ma == jega->ca) && cursoron);
int drawcursor = ((*memaddr == jega->cursoraddr) && cursoron);
uint32_t chr;
uint32_t attr;
@@ -399,9 +399,9 @@ jega_render_text(void *priv)
p += charwidth;
}
}
*ma += 4;
*memaddr += 4;
}
*ma &= 0x3ffff;
*memaddr &= 0x3ffff;
}
}
@@ -523,7 +523,7 @@ jega_out(uint16_t addr, uint8_t val, void *priv)
break;
case RCCLH:
case RCCLL:
jega->ca = jega->regs[RCCLH] << 10 | jega->regs[RCCLL] << 2;
jega->cursoraddr = jega->regs[RCCLH] << 10 | jega->regs[RCCLL] << 2;
break;
case RCMOD:
jega->cursoron = (val & 0x80);

View File

@@ -6,16 +6,19 @@
*
* This file is part of the 86Box distribution.
*
* MDA emulation.
* IBM Monochrome Display and Printer Adapter emulation.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Connor Hyde, <mario64crashed@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2025 Miran Grca.
* Copyright 2025 starfrost / Connor Hyde
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -33,7 +36,17 @@
#include <86box/vid_mda.h>
#include <86box/plat_unused.h>
static int mdacols[256][2][2];
// Enumerates MDA monitor types
enum mda_monitor_type_e {
MDA_MONITOR_TYPE_DEFAULT = 0, // Default MDA monitor type.
MDA_MONITOR_TYPE_GREEN = 1, // Green phosphor
MDA_MONITOR_TYPE_AMBER = 2, // Amber phosphor
MDA_MONITOR_TYPE_GRAY = 3, // Gray phosphor
MDA_MONITOR_TYPE_RGBI = 4, // RGBI colour monitor with modified rev1 or rev0 MDA card for colour support
} mda_monitor_type;
// [attr][blink][fg]
static int mda_attr_to_color_table[256][2][2];
static video_timings_t timing_mda = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
@@ -44,32 +57,31 @@ mda_out(uint16_t addr, uint8_t val, void *priv)
{
mda_t *mda = (mda_t *) priv;
switch (addr) {
case 0x3b0:
case 0x3b2:
case 0x3b4:
case 0x3b6:
mda->crtcreg = val & 31;
return;
case 0x3b1:
case 0x3b3:
case 0x3b5:
case 0x3b7:
mda->crtc[mda->crtcreg] = val;
if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{
mda->crtc[10] = 0xb;
mda->crtc[11] = 0xc;
}
mda_recalctimings(mda);
return;
case 0x3b8:
mda->ctrl = val;
return;
if (addr < MDA_REGISTER_START
|| addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case
return;
switch (addr) {
case MDA_REGISTER_MODE_CONTROL:
mda->mode = val;
return;
default:
break;
}
// addr & 1 == 1 = MDA_REGISTER_CRTC_DATA
// otherwise MDA_REGISTER_CRTC_INDEX
if (addr & 1) {
mda->crtc[mda->crtcreg] = val;
if (mda->crtc[MDA_CRTC_CURSOR_START] == 6
&& mda->crtc[MDA_CRTC_CURSOR_END] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/
{
mda->crtc[MDA_CRTC_CURSOR_START] = 0xb;
mda->crtc[MDA_CRTC_CURSOR_END] = 0xc;
}
mda_recalctimings(mda);
} else
mda->crtcreg = val & 31;
}
uint8_t
@@ -78,23 +90,23 @@ mda_in(uint16_t addr, void *priv)
const mda_t *mda = (mda_t *) priv;
switch (addr) {
case 0x3b0:
case 0x3b2:
case 0x3b4:
case 0x3b6:
return mda->crtcreg;
case 0x3b1:
case 0x3b3:
case 0x3b5:
case 0x3b7:
return mda->crtc[mda->crtcreg];
case 0x3ba:
return mda->stat | 0xF0;
case MDA_REGISTER_CRT_STATUS:
return mda->status | 0xF0;
default:
if (addr < MDA_REGISTER_START
|| addr > MDA_REGISTER_CRT_STATUS) // Maintain old behaviour for printer registers, just in case
return 0xFF;
// MDA_REGISTER_CRTC_DATA
if (addr & 1)
return mda->crtc[mda->crtcreg];
else
return mda->crtcreg;
break;
}
return 0xff;
return 0xFF;
}
void
@@ -118,8 +130,8 @@ mda_recalctimings(mda_t *mda)
double _dispontime;
double _dispofftime;
double disptime;
disptime = mda->crtc[0] + 1;
_dispontime = mda->crtc[1];
disptime = mda->crtc[MDA_CRTC_HTOTAL] + 1;
_dispontime = mda->crtc[MDA_CRTC_HDISP];
_dispofftime = disptime - _dispontime;
_dispontime *= MDACONST;
_dispofftime *= MDACONST;
@@ -130,59 +142,141 @@ mda_recalctimings(mda_t *mda)
void
mda_poll(void *priv)
{
mda_t *mda = (mda_t *) priv;
uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int c;
int oldvc;
mda_t *mda = (mda_t *) priv;
uint16_t cursoraddr = (mda->crtc[MDA_CRTC_CURSOR_ADDR_LOW] | (mda->crtc[MDA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
bool drawcursor;
int32_t oldvc;
uint8_t chr;
uint8_t attr;
int oldsc;
int blink;
int32_t scanline_old;
int32_t blink;
VIDEO_MONITOR_PROLOGUE()
if (!mda->linepos) {
timer_advance_u64(&mda->timer, mda->dispofftime);
mda->stat |= 1;
mda->status |= 1;
mda->linepos = 1;
oldsc = mda->sc;
if ((mda->crtc[8] & 3) == 3)
mda->sc = (mda->sc << 1) & 7;
scanline_old = mda->scanline;
if ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3)
mda->scanline = (mda->scanline << 1) & 7;
if (mda->dispon) {
if (mda->displine < mda->firstline) {
mda->firstline = mda->displine;
video_wait_for_buffer();
}
mda->lastline = mda->displine;
for (x = 0; x < mda->crtc[1]; x++) {
chr = mda->vram[(mda->ma << 1) & 0xfff];
attr = mda->vram[((mda->ma << 1) + 1) & 0xfff];
drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron);
blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
if (mda->sc == 12 && ((attr & 7) == 1)) {
for (c = 0; c < 9; c++)
buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1];
} else {
for (c = 0; c < 8; c++)
buffer32->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr + mda->fontbase][mda->sc] & (1 << (c ^ 7))) ? 1 : 0];
if ((chr & ~0x1f) == 0xc0)
buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr + mda->fontbase][mda->sc] & 1];
else
buffer32->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0];
for (uint32_t x = 0; x < mda->crtc[MDA_CRTC_HDISP]; x++) {
chr = mda->vram[(mda->memaddr << 1) & 0xfff];
attr = mda->vram[((mda->memaddr << 1) + 1) & 0xfff];
drawcursor = ((mda->memaddr == cursoraddr) && mda->cursorvisible && mda->cursoron);
blink = ((mda->blink & 16) && (mda->mode & MDA_MODE_BLINK) && (attr & 0x80) && !drawcursor);
// Colours that will be used
int32_t color_bg = 0, color_fg = 0;
// If we are using an RGBI monitor allow colour
if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI
&& !(mda->mode & MDA_MODE_BW)) {
color_bg = (attr >> 4) & 0x0F;
color_fg = (attr & 0x0F);
// turn off bright bg colours in blink mode
if ((mda->mode & MDA_MODE_BLINK)
&& (color_bg & 0x8))
color_bg & ~(0x8);
// black-on-non black or white colours forced to white
// grey-on-colours forced to bright white
bool special_treatment = (color_bg != 0 && color_bg != 7);
if (color_fg == MDA_COLOR_GREY
&& special_treatment)
color_fg = MDA_COLOR_BRIGHT_WHITE;
if (color_fg == 0
&& special_treatment)
color_fg = MDA_COLOR_GREY;
// gray is black
if (color_fg == MDA_COLOR_GREY
&& (color_bg == MDA_COLOR_GREY || color_bg == MDA_COLOR_BLACK))
color_fg = MDA_COLOR_BLACK;
}
mda->ma++;
if (mda->scanline == 12
&& ((attr & 7) == 1)) { // underline
for (uint32_t column = 0; column < 9; column++) {
if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI
&& !(mda->mode & MDA_MODE_BW)) {
buffer32->line[mda->displine][(x * 9) + column] = CGAPAL_CGA_START + color_fg;
} else
buffer32->line[mda->displine][(x * 9) + column] = mda_attr_to_color_table[attr][blink][1];
}
} else { // character
for (uint32_t column = 0; column < 8; column++) {
// bg=0, fg=1
bool is_fg = (fontdatm[chr + mda->fontbase][mda->scanline] & (1 << (column ^ 7))) ? 1 : 0;
uint32_t font_char = mda_attr_to_color_table[attr][blink][is_fg];
if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI
&& !(mda->mode & MDA_MODE_BW)) {
if (!is_fg)
font_char = CGAPAL_CGA_START + color_bg;
else
font_char = CGAPAL_CGA_START + color_fg;
}
buffer32->line[mda->displine][(x * 9) + column] = font_char;
}
// these characters (C0-DF) have their background extended to their 9th column
if ((chr & ~0x1f) == 0xc0) {
bool is_fg = fontdatm[chr + mda->fontbase][mda->scanline] & 1;
uint32_t final_result = mda_attr_to_color_table[attr][blink][is_fg];
if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI
&& !(mda->mode & MDA_MODE_BW)) {
if (!is_fg)
final_result = CGAPAL_CGA_START + color_bg;
else
final_result = CGAPAL_CGA_START + color_fg;
}
buffer32->line[mda->displine][(x * 9) + 8] = final_result;
} else {
if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI
&& !(mda->mode & MDA_MODE_BW)) {
buffer32->line[mda->displine][(x * 9) + 8] = CGAPAL_CGA_START + color_bg;
} else
buffer32->line[mda->displine][(x * 9) + 8] = mda_attr_to_color_table[attr][blink][0];
}
}
mda->memaddr++;
if (drawcursor) {
for (c = 0; c < 9; c++)
buffer32->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1];
for (uint32_t column = 0; column < 9; column++) {
if (mda->monitor_type == MDA_MONITOR_TYPE_RGBI
&& !(mda->mode & MDA_MODE_BW)) {
buffer32->line[mda->displine][(x * 9) + column] ^= CGAPAL_CGA_START + color_fg;
} else
buffer32->line[mda->displine][(x * 9) + column] ^= mda_attr_to_color_table[attr][0][1];
}
}
}
video_process_8(mda->crtc[1] * 9, mda->displine);
video_process_8(mda->crtc[MDA_CRTC_HDISP] * 9, mda->displine);
}
mda->sc = oldsc;
if (mda->vc == mda->crtc[7] && !mda->sc) {
mda->stat |= 8;
mda->scanline = scanline_old;
if (mda->vc == mda->crtc[MDA_CRTC_VSYNC] && !mda->scanline) {
mda->status |= 8;
}
mda->displine++;
if (mda->displine >= 500)
@@ -190,54 +284,60 @@ mda_poll(void *priv)
} else {
timer_advance_u64(&mda->timer, mda->dispontime);
if (mda->dispon)
mda->stat &= ~1;
mda->status &= ~1;
mda->linepos = 0;
if (mda->vsynctime) {
mda->vsynctime--;
if (!mda->vsynctime) {
mda->stat &= ~8;
mda->status &= ~8;
}
}
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) {
mda->con = 0;
mda->coff = 1;
if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_END] & 31)
|| ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3
&& mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_END] & 31) >> 1))) {
mda->cursorvisible = 0;
}
if (mda->vadj) {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->scanline++;
mda->scanline &= 31;
mda->memaddr = mda->memaddr_backup;
mda->vadj--;
if (!mda->vadj) {
mda->dispon = 1;
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
mda->sc = 0;
mda->dispon = 1;
mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
mda->scanline = 0;
}
} else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) {
mda->maback = mda->ma;
mda->sc = 0;
oldvc = mda->vc;
} else if (mda->scanline == mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR]
|| ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3
&& mda->scanline == (mda->crtc[MDA_CRTC_MAX_SCANLINE_ADDR] >> 1))) {
mda->memaddr_backup = mda->memaddr;
mda->scanline = 0;
oldvc = mda->vc;
mda->vc++;
mda->vc &= 127;
if (mda->vc == mda->crtc[6])
if (mda->vc == mda->crtc[MDA_CRTC_VDISP])
mda->dispon = 0;
if (oldvc == mda->crtc[4]) {
if (oldvc == mda->crtc[MDA_CRTC_VTOTAL]) {
mda->vc = 0;
mda->vadj = mda->crtc[5];
mda->vadj = mda->crtc[MDA_CRTC_VTOTAL_ADJUST];
if (!mda->vadj)
mda->dispon = 1;
if (!mda->vadj)
mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff;
if ((mda->crtc[10] & 0x60) == 0x20)
mda->memaddr = mda->memaddr_backup = (mda->crtc[MDA_CRTC_START_ADDR_LOW] | (mda->crtc[MDA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
if ((mda->crtc[MDA_CRTC_CURSOR_START] & 0x60) == 0x20)
mda->cursoron = 0;
else
mda->cursoron = mda->blink & 16;
}
if (mda->vc == mda->crtc[7]) {
if (mda->vc == mda->crtc[MDA_CRTC_VSYNC]) {
mda->dispon = 0;
mda->displine = 0;
mda->vsynctime = 16;
if (mda->crtc[7]) {
x = mda->crtc[1] * 9;
if (mda->crtc[MDA_CRTC_VSYNC]) {
uint32_t x = mda->crtc[MDA_CRTC_HDISP] * 9;
mda->lastline++;
if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) {
xsize = x;
@@ -253,8 +353,8 @@ mda_poll(void *priv)
}
video_blit_memtoscreen(0, mda->firstline, xsize, ysize);
frames++;
video_res_x = mda->crtc[1];
video_res_y = mda->crtc[6];
video_res_x = mda->crtc[MDA_CRTC_HDISP];
video_res_y = mda->crtc[MDA_CRTC_VDISP];
video_bpp = 0;
}
mda->firstline = 1000;
@@ -262,12 +362,15 @@ mda_poll(void *priv)
mda->blink++;
}
} else {
mda->sc++;
mda->sc &= 31;
mda->ma = mda->maback;
mda->scanline++;
mda->scanline &= 31;
mda->memaddr = mda->memaddr_backup;
}
if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) {
mda->con = 1;
if (mda->scanline == (mda->crtc[MDA_CRTC_CURSOR_START] & 31)
|| ((mda->crtc[MDA_CRTC_INTERLACE] & 3) == 3
&& mda->scanline == ((mda->crtc[MDA_CRTC_CURSOR_START] & 31) >> 1))) {
mda->cursorvisible = 1;
}
}
VIDEO_MONITOR_EPILOGUE();
@@ -276,30 +379,32 @@ mda_poll(void *priv)
void
mda_init(mda_t *mda)
{
for (uint16_t c = 0; c < 256; c++) {
mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16;
if (c & 8)
mdacols[c][0][1] = 15 + 16;
for (uint16_t attr = 0; attr < 256; attr++) {
mda_attr_to_color_table[attr][0][0] = mda_attr_to_color_table[attr][1][0] = mda_attr_to_color_table[attr][1][1] = 16;
if (attr & 8)
mda_attr_to_color_table[attr][0][1] = 15 + 16;
else
mdacols[c][0][1] = 7 + 16;
mda_attr_to_color_table[attr][0][1] = 7 + 16;
}
mdacols[0x70][0][1] = 16;
mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15;
mdacols[0xF0][0][1] = 16;
mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15;
mdacols[0x78][0][1] = 16 + 7;
mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15;
mdacols[0xF8][0][1] = 16 + 7;
mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15;
mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16;
mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16;
mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16;
mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16;
mda_attr_to_color_table[0x70][0][1] = 16;
mda_attr_to_color_table[0x70][0][0] = mda_attr_to_color_table[0x70][1][0] = mda_attr_to_color_table[0x70][1][1] = CGAPAL_CGA_START + 15;
mda_attr_to_color_table[0xF0][0][1] = 16;
mda_attr_to_color_table[0xF0][0][0] = mda_attr_to_color_table[0xF0][1][0] = mda_attr_to_color_table[0xF0][1][1] = CGAPAL_CGA_START + 15;
mda_attr_to_color_table[0x78][0][1] = CGAPAL_CGA_START + 7;
mda_attr_to_color_table[0x78][0][0] = mda_attr_to_color_table[0x78][1][0] = mda_attr_to_color_table[0x78][1][1] = CGAPAL_CGA_START + 15;
mda_attr_to_color_table[0xF8][0][1] = CGAPAL_CGA_START + 7;
mda_attr_to_color_table[0xF8][0][0] = mda_attr_to_color_table[0xF8][1][0] = mda_attr_to_color_table[0xF8][1][1] = CGAPAL_CGA_START + 15;
mda_attr_to_color_table[0x00][0][1] = mda_attr_to_color_table[0x00][1][1] = 16;
mda_attr_to_color_table[0x08][0][1] = mda_attr_to_color_table[0x08][1][1] = 16;
mda_attr_to_color_table[0x80][0][1] = mda_attr_to_color_table[0x80][1][1] = 16;
mda_attr_to_color_table[0x88][0][1] = mda_attr_to_color_table[0x88][1][1] = 16;
overscan_x = overscan_y = 0;
mda->monitor_index = monitor_index_global;
cga_palette = device_get_config_int("rgb_type") << 1;
mda->monitor_type = device_get_config_int("rgb_type");
cga_palette = mda->monitor_type << 1;
if (cga_palette > 6) {
cga_palette = 0;
}
@@ -317,7 +422,7 @@ mda_standalone_init(UNUSED(const device_t *info))
mda->vram = malloc(0x1000);
switch(device_get_config_int("font")) {
switch (device_get_config_int("font")) {
case 0:
loadfont(FONT_IBM_MDA_437_PATH, 0);
break;
@@ -354,7 +459,7 @@ mda_standalone_init(UNUSED(const device_t *info))
void
mda_setcol(int chr, int blink, int fg, uint8_t cga_ink)
{
mdacols[chr][blink][fg] = 16 + cga_ink;
mda_attr_to_color_table[chr][blink][fg] = CGAPAL_CGA_START + cga_ink;
}
void
@@ -375,7 +480,7 @@ mda_speed_changed(void *priv)
}
static const device_config_t mda_config[] = {
// clang-format off
// clang-format off
{
.name = "rgb_type",
.description = "Display type",
@@ -384,12 +489,14 @@ static const device_config_t mda_config[] = {
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "Default", .value = 0 },
{ .description = "Green", .value = 1 },
{ .description = "Amber", .value = 2 },
{ .description = "Gray", .value = 3 },
{ .description = "" }
.selection =
{
{ .description = "Default", .value = MDA_MONITOR_TYPE_DEFAULT },
{ .description = "Green", .value = MDA_MONITOR_TYPE_GREEN },
{ .description = "Amber", .value = MDA_MONITOR_TYPE_AMBER },
{ .description = "Gray", .value = MDA_MONITOR_TYPE_GRAY },
{ .description = "Generic RGBI color monitor", .value = MDA_MONITOR_TYPE_RGBI },
{ .description = "" }
},
.bios = { { 0 } }
},
@@ -401,17 +508,18 @@ static const device_config_t mda_config[] = {
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "US (CP 437)", .value = 0 },
.selection =
{
{ .description = "US (CP 437)", .value = 0 },
{ .description = "IBM Nordic (CP 437-Nordic)", .value = 1 },
{ .description = "Czech Kamenicky (CP 895) #1", .value = 2 },
{ .description = "Czech Kamenicky (CP 895) #2", .value = 3 },
{ .description = "" }
{ .description = "" }
},
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
// clang-format on
};
const device_t mda_device = {

View File

@@ -736,7 +736,7 @@ mystique_out(uint16_t addr, uint8_t val, void *priv)
if ((svga->crtcreg & 0x3f) < 0xE || (svga->crtcreg & 0x3f) > 0x10) {
if (((svga->crtcreg & 0x3f) == 0xc) || ((svga->crtcreg & 0x3f) == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
@@ -768,24 +768,24 @@ mystique_out(uint16_t addr, uint8_t val, void *priv)
if (!(mystique->type >= MGA_2164W))
svga->rowoffset <<= 1;
svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) |
svga->memaddr_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) |
(svga->crtc[0xc] << 8) | svga->crtc[0xd];
if ((mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8))) {
svga->rowoffset <<= 1;
svga->ma_latch <<= 1;
svga->memaddr_latch <<= 1;
}
if (!(mystique->type >= MGA_2164W))
svga->ma_latch <<= 1;
svga->memaddr_latch <<= 1;
if (svga->ma_latch != mystique->ma_latch_old) {
if (svga->memaddr_latch != mystique->ma_latch_old) {
if (svga->interlace && svga->oddeven)
svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) +
(svga->ma_latch << 2) + (svga->rowoffset << 1);
svga->memaddr_backup = (svga->memaddr_backup - (mystique->ma_latch_old << 2)) +
(svga->memaddr_latch << 2) + (svga->rowoffset << 1);
else
svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) +
(svga->ma_latch << 2);
mystique->ma_latch_old = svga->ma_latch;
svga->memaddr_backup = (svga->memaddr_backup - (mystique->ma_latch_old << 2)) +
(svga->memaddr_latch << 2);
mystique->ma_latch_old = svga->memaddr_latch;
}
}
@@ -895,9 +895,9 @@ mystique_vblank_start(svga_t *svga)
mystique_t *mystique = (mystique_t *) svga->priv;
if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) {
svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd];
svga->memaddr_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd];
if (mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8))
svga->ma_latch <<= 1;
svga->memaddr_latch <<= 1;
}
}
@@ -984,29 +984,29 @@ mystique_recalctimings(svga_t *svga)
svga->lut_map = !!(mystique->xmiscctrl & XMISCCTRL_RAMCS);
if (mystique->type >= MGA_1064SG)
svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd];
svga->memaddr_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 16) | (svga->crtc[0xc] << 8) | svga->crtc[0xd];
if ((mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8))) {
svga->rowoffset <<= 1;
if (mystique->type >= MGA_1064SG)
svga->ma_latch <<= 1;
svga->memaddr_latch <<= 1;
}
if (mystique->type >= MGA_1064SG) {
/*Mystique and later, unlike most SVGA cards, allows display start to take
effect mid-screen*/
if (!(mystique->type >= MGA_2164W))
svga->ma_latch <<= 1;
/* Only change maback so the new display start will take effect on the next
svga->memaddr_latch <<= 1;
/* Only change memaddr_backup so the new display start will take effect on the next
horizontal retrace. */
if (svga->ma_latch != mystique->ma_latch_old) {
if (svga->memaddr_latch != mystique->ma_latch_old) {
if (svga->interlace && svga->oddeven)
svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) +
(svga->ma_latch << 2) + (svga->rowoffset << 1);
svga->memaddr_backup = (svga->memaddr_backup - (mystique->ma_latch_old << 2)) +
(svga->memaddr_latch << 2) + (svga->rowoffset << 1);
else
svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) +
(svga->ma_latch << 2);
mystique->ma_latch_old = svga->ma_latch;
svga->memaddr_backup = (svga->memaddr_backup - (mystique->ma_latch_old << 2)) +
(svga->memaddr_latch << 2);
mystique->ma_latch_old = svga->memaddr_latch;
}
if (!(mystique->type >= MGA_2164W))

View File

@@ -124,7 +124,7 @@ oti_out(uint16_t addr, uint8_t val, void *priv)
if ((idx < 0x0e) || (idx > 0x10)) {
if (idx == 0x0c || idx == 0x0d) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
@@ -393,9 +393,9 @@ oti_recalctimings(svga_t *svga)
if (oti->chip_id > 0) {
if (oti->regs[0x14] & 0x08)
svga->ma_latch |= 0x10000;
svga->memaddr_latch |= 0x10000;
if (oti->regs[0x16] & 0x08)
svga->ma_latch |= 0x20000;
svga->memaddr_latch |= 0x20000;
if (oti->regs[0x14] & 0x01)
svga->vtotal += 0x400;

View File

@@ -245,7 +245,7 @@ paradise_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);

703
src/video/vid_pcjr.c Normal file
View File

@@ -0,0 +1,703 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* IBM PCjr video subsystem emulation
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Connor Hyde / starfrost <mario64crashed@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2025 starfrost
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mem.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/video.h>
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#include <86box/m_pcjr.h>
static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/
static uint8_t crtcmask[32] = {
0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f,
0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static void
recalc_address(pcjr_t *pcjr)
{
uint8_t masked_memctrl = pcjr->memctrl;
/* According to the Technical Reference, bits 2 and 5 are
ignored if there is only 64k of RAM and there are only
4 pages. */
if (mem_size < 128)
masked_memctrl &= ~0x24;
if ((pcjr->memctrl & 0xc0) == 0xc0) {
pcjr->vram = &ram[(masked_memctrl & 0x06) << 14];
pcjr->b8000 = &ram[(masked_memctrl & 0x30) << 11];
} else {
pcjr->vram = &ram[(masked_memctrl & 0x07) << 14];
pcjr->b8000 = &ram[(masked_memctrl & 0x38) << 11];
}
}
void
pcjr_recalc_timings(pcjr_t *pcjr)
{
double _dispontime;
double _dispofftime;
double disptime;
if (pcjr->array[0] & 1) {
disptime = pcjr->crtc[0] + 1;
_dispontime = pcjr->crtc[1];
} else {
disptime = (pcjr->crtc[0] + 1) << 1;
_dispontime = pcjr->crtc[1] << 1;
}
_dispofftime = disptime - _dispontime;
_dispontime *= CGACONST;
_dispofftime *= CGACONST;
pcjr->dispontime = (uint64_t) (_dispontime);
pcjr->dispofftime = (uint64_t) (_dispofftime);
}
static int
vid_get_h_overscan_size(pcjr_t *pcjr)
{
int ret;
if (pcjr->array[0] & 1)
ret = 128;
else
ret = 256;
return ret;
}
static void
vid_out(uint16_t addr, uint8_t val, void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
uint8_t old;
switch (addr) {
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
pcjr->crtcreg = val & 0x1f;
return;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
old = pcjr->crtc[pcjr->crtcreg];
pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg];
if (pcjr->crtcreg == 2)
overscan_x = vid_get_h_overscan_size(pcjr);
if (old != val) {
if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) {
pcjr->fullchange = changeframecount;
pcjr_recalc_timings(pcjr);
}
}
return;
case 0x3da:
if (!pcjr->array_ff)
pcjr->array_index = val & 0x1f;
else {
if (pcjr->array_index & 0x10)
val &= 0x0f;
pcjr->array[pcjr->array_index & 0x1f] = val;
if (!(pcjr->array_index & 0x1f))
update_cga16_color(val);
}
pcjr->array_ff = !pcjr->array_ff;
break;
case 0x3df:
pcjr->memctrl = val;
pcjr->pa = val; /* The PCjr BIOS expects the value written to 3DF to
then be readable from port 60, others it errors out
with only 64k RAM set (but somehow, still works with
128k or more RAM). */
pcjr->addr_mode = val >> 6;
recalc_address(pcjr);
break;
default:
break;
}
}
static uint8_t
vid_in(uint16_t addr, void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x3d0:
case 0x3d2:
case 0x3d4:
case 0x3d6:
ret = pcjr->crtcreg;
break;
case 0x3d1:
case 0x3d3:
case 0x3d5:
case 0x3d7:
ret = pcjr->crtc[pcjr->crtcreg];
break;
case 0x3da:
pcjr->array_ff = 0;
pcjr->status ^= 0x10;
ret = pcjr->status;
break;
default:
break;
}
return ret;
}
static void
vid_write(uint32_t addr, uint8_t val, void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
if (pcjr->memctrl == -1)
return;
pcjr->b8000[addr & 0x3fff] = val;
}
static uint8_t
vid_read(uint32_t addr, void *priv)
{
const pcjr_t *pcjr = (pcjr_t *) priv;
if (pcjr->memctrl == -1)
return 0xff;
return (pcjr->b8000[addr & 0x3fff]);
}
static int
vid_get_h_overscan_delta(pcjr_t *pcjr)
{
int def;
int coef;
int ret;
switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) {
case 0x13: /*320x200x16*/
def = 0x56;
coef = 8;
break;
case 0x12: /*160x200x16*/
def = 0x2c; /* I'm going to assume a datasheet erratum here. */
coef = 16;
break;
case 0x03: /*640x200x4*/
def = 0x56;
coef = 8;
break;
case 0x01: /*80 column text*/
def = 0x5a;
coef = 8;
break;
case 0x00: /*40 column text*/
default:
def = 0x2c;
coef = 16;
break;
case 0x02: /*320x200x4*/
def = 0x2b;
coef = 16;
break;
case 0x102: /*640x200x2*/
def = 0x2b;
coef = 16;
break;
}
ret = pcjr->crtc[0x02] - def;
if (ret < -8)
ret = -8;
if (ret > 8)
ret = 8;
return ret * coef;
}
static void
vid_blit_h_overscan(pcjr_t *pcjr)
{
int cols = (pcjr->array[2] & 0xf) + 16;;
int y0 = pcjr->firstline << 1;
int y = (pcjr->lastline << 1) + 16;
int ho_s = vid_get_h_overscan_size(pcjr);
int i;
int x;
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
for (i = 0; i < 16; i++) {
hline(buffer32, 0, y0 + i, x, cols);
hline(buffer32, 0, y + i, x, cols);
if (pcjr->composite) {
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y0 + i]);
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y + i]);
} else {
video_process_8(x, y0 + i);
video_process_8(x, y + i);
}
}
}
static void
vid_poll(void *priv)
{
pcjr_t *pcjr = (pcjr_t *) priv;
uint16_t cursoraddr = (pcjr->crtc[15] | (pcjr->crtc[14] << 8)) & 0x3fff;
int drawcursor;
int x;
int xs_temp;
int ys_temp;
int oldvc;
uint8_t chr;
uint8_t attr;
uint16_t dat;
int cols[4];
int scanline_old;
int l = (pcjr->displine << 1) + 16;
int ho_s = vid_get_h_overscan_size(pcjr);
int ho_d = vid_get_h_overscan_delta(pcjr) + (ho_s / 2);
if (!pcjr->linepos) {
timer_advance_u64(&pcjr->timer, pcjr->dispofftime);
pcjr->status &= ~1;
pcjr->linepos = 1;
scanline_old = pcjr->scanline;
if ((pcjr->crtc[8] & 3) == 3)
pcjr->scanline = (pcjr->scanline << 1) & 7;
if (pcjr->dispon) {
uint16_t offset = 0;
uint16_t mask = 0x1fff;
if (pcjr->displine < pcjr->firstline) {
pcjr->firstline = pcjr->displine;
video_wait_for_buffer();
}
pcjr->lastline = pcjr->displine;
cols[0] = (pcjr->array[2] & 0xf) + 16;
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
}
switch (pcjr->addr_mode) {
case 0: /*Alpha*/
offset = 0;
mask = 0x3fff;
break;
case 1: /*Low resolution graphics*/
offset = (pcjr->scanline & 1) * 0x2000;
break;
case 3: /*High resolution graphics*/
offset = (pcjr->scanline & 3) * 0x2000;
break;
default:
break;
}
switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) {
case 0x13: /*320x200x16*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] =
buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] =
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] =
buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] =
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] =
buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] =
buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x12: /*160x200x16*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] =
buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] =
buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] =
buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] =
pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] =
buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] =
buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] =
buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] =
pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 8] = buffer32->line[l][ef_x + 9] =
buffer32->line[l][ef_x + 10] = buffer32->line[l][ef_x + 11] =
buffer32->line[l + 1][ef_x + 8] = buffer32->line[l + 1][ef_x + 9] =
buffer32->line[l + 1][ef_x + 10] = buffer32->line[l + 1][ef_x + 11] =
pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
buffer32->line[l][ef_x + 12] = buffer32->line[l][ef_x + 13] =
buffer32->line[l][ef_x + 14] = buffer32->line[l][ef_x + 15] =
buffer32->line[l + 1][ef_x + 12] = buffer32->line[l + 1][ef_x + 13] =
buffer32->line[l + 1][ef_x + 14] = buffer32->line[l + 1][ef_x + 15] =
pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16;
}
break;
case 0x03: /*640x200x4*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset];
pcjr->memaddr++;
for (uint8_t c = 0; c < 8; c++) {
chr = (dat >> 7) & 1;
chr |= ((dat >> 14) & 2);
buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] =
pcjr->array[(chr & pcjr->array[1] & 0x0f) + 16] + 16;
dat <<= 1;
}
}
break;
case 0x01: /*80 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 3) + ho_d;
chr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
drawcursor = ((pcjr->memaddr == cursoraddr) && pcjr->cursorvisible && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
if (pcjr->scanline & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + c] =
buffer32->line[l + 1][ef_x + c] = cols[0];
else
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + c] =
buffer32->line[l + 1][ef_x + c] =
cols[(fontdat[chr][pcjr->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor)
for (uint8_t c = 0; c < 8; c++) {
buffer32->line[l][ef_x + c] ^= 15;
buffer32->line[l + 1][ef_x + c] ^= 15;
}
pcjr->memaddr++;
}
break;
case 0x00: /*40 column text*/
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
chr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset];
attr = pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
drawcursor = ((pcjr->memaddr == cursoraddr) && pcjr->cursorvisible && pcjr->cursoron);
if (pcjr->array[3] & 4) {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16;
if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor)
cols[1] = cols[0];
} else {
cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16;
cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16;
}
pcjr->memaddr++;
if (pcjr->scanline & 8)
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[0];
else
for (uint8_t c = 0; c < 8; c++)
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] =
cols[(fontdat[chr][pcjr->scanline & 7] & (1 << (c ^ 7))) ? 1 : 0];
if (drawcursor)
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[l][ef_x + c] ^= 15;
buffer32->line[l + 1][ef_x + c] ^= 15;
}
}
break;
case 0x02: /*320x200x4*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
cols[2] = pcjr->array[2 + 16] + 16;
cols[3] = pcjr->array[3 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
for (uint8_t c = 0; c < 8; c++) {
buffer32->line[l][ef_x + (c << 1)] =
buffer32->line[l][ef_x + (c << 1) + 1] =
buffer32->line[l + 1][ef_x + (c << 1)] =
buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[dat >> 14];
dat <<= 2;
}
}
break;
case 0x102: /*640x200x2*/
cols[0] = pcjr->array[0 + 16] + 16;
cols[1] = pcjr->array[1 + 16] + 16;
for (x = 0; x < pcjr->crtc[1]; x++) {
int ef_x = (x << 4) + ho_d;
dat = (pcjr->vram[((pcjr->memaddr << 1) & mask) + offset] << 8) |
pcjr->vram[((pcjr->memaddr << 1) & mask) + offset + 1];
pcjr->memaddr++;
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] =
cols[dat >> 15];
dat <<= 1;
}
}
break;
default:
break;
}
} else {
if (pcjr->array[3] & 4) {
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16);
}
} else {
cols[0] = pcjr->array[0 + 16] + 16;
if (pcjr->array[0] & 1) {
hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]);
} else {
hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]);
}
}
}
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
if (pcjr->composite) {
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l]);
Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l + 1]);
} else {
video_process_8(x, l);
video_process_8(x, l + 1);
}
pcjr->scanline = scanline_old;
if (pcjr->vc == pcjr->crtc[7] && !pcjr->scanline) {
pcjr->status |= 8;
}
pcjr->displine++;
if (pcjr->displine >= 360)
pcjr->displine = 0;
} else {
timer_advance_u64(&pcjr->timer, pcjr->dispontime);
if (pcjr->dispon)
pcjr->status |= 1;
pcjr->linepos = 0;
if (pcjr->vsynctime) {
pcjr->vsynctime--;
if (!pcjr->vsynctime) {
pcjr->status &= ~8;
}
}
if (pcjr->scanline == (pcjr->crtc[11] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->scanline == ((pcjr->crtc[11] & 31) >> 1))) {
pcjr->cursorvisible = 0;
}
if (pcjr->vadj) {
pcjr->scanline++;
pcjr->scanline &= 31;
pcjr->memaddr = pcjr->memaddr_backup;
pcjr->vadj--;
if (!pcjr->vadj) {
pcjr->dispon = 1;
pcjr->memaddr = pcjr->memaddr_backup = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
pcjr->scanline = 0;
}
} else if (pcjr->scanline == pcjr->crtc[9] || ((pcjr->crtc[8] & 3) == 3 && pcjr->scanline == (pcjr->crtc[9] >> 1))) {
pcjr->memaddr_backup = pcjr->memaddr;
pcjr->scanline = 0;
oldvc = pcjr->vc;
pcjr->vc++;
pcjr->vc &= 127;
if (pcjr->vc == pcjr->crtc[6])
pcjr->dispon = 0;
if (oldvc == pcjr->crtc[4]) {
pcjr->vc = 0;
pcjr->vadj = pcjr->crtc[5];
if (!pcjr->vadj)
pcjr->dispon = 1;
if (!pcjr->vadj)
pcjr->memaddr = pcjr->memaddr_backup = (pcjr->crtc[13] | (pcjr->crtc[12] << 8)) & 0x3fff;
if ((pcjr->crtc[10] & 0x60) == 0x20)
pcjr->cursoron = 0;
else
pcjr->cursoron = pcjr->blink & 16;
}
if (pcjr->vc == pcjr->crtc[7]) {
pcjr->dispon = 0;
pcjr->displine = 0;
pcjr->vsynctime = 16;
picint(1 << 5);
if (pcjr->crtc[7]) {
if (pcjr->array[0] & 1)
x = (pcjr->crtc[1] << 3) + ho_s;
else
x = (pcjr->crtc[1] << 4) + ho_s;
pcjr->lastline++;
xs_temp = x;
ys_temp = (pcjr->lastline - pcjr->firstline) << 1;
if ((xs_temp > 0) && (ys_temp > 0)) {
int actual_ys = ys_temp;
if (xs_temp < 64)
xs_temp = 656;
if (ys_temp < 32)
ys_temp = 400;
if (!enable_overscan)
xs_temp -= ho_s;
if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) {
xsize = xs_temp;
ysize = ys_temp;
set_screen_size(xsize, ysize + (enable_overscan ? 32 : 0));
if (video_force_resize_get())
video_force_resize_set(0);
}
vid_blit_h_overscan(pcjr);
if (enable_overscan) {
video_blit_memtoscreen(0, pcjr->firstline << 1,
xsize, actual_ys + 32);
} else if (pcjr->apply_hd) {
video_blit_memtoscreen(ho_s / 2, (pcjr->firstline << 1) + 16,
xsize, actual_ys);
} else {
video_blit_memtoscreen(ho_d, (pcjr->firstline << 1) + 16,
xsize, actual_ys);
}
}
frames++;
video_res_x = xsize;
video_res_y = ysize;
}
pcjr->firstline = 1000;
pcjr->lastline = 0;
pcjr->blink++;
}
} else {
pcjr->scanline++;
pcjr->scanline &= 31;
pcjr->memaddr = pcjr->memaddr_backup;
}
if (pcjr->scanline == (pcjr->crtc[10] & 31) || ((pcjr->crtc[8] & 3) == 3 && pcjr->scanline == ((pcjr->crtc[10] & 31) >> 1)))
pcjr->cursorvisible = 1;
}
}
void
pcjr_vid_init(pcjr_t *pcjr)
{
int display_type;
video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram);
pcjr->memctrl = -1;
if (mem_size < 128)
pcjr->memctrl &= ~0x24;
display_type = device_get_config_int("display_type");
pcjr->composite = (display_type != PCJR_RGB);
pcjr->apply_hd = device_get_config_int("apply_hd");
overscan_x = 256;
overscan_y = 32;
mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000,
vid_read, NULL, NULL,
vid_write, NULL, NULL, NULL, 0, pcjr);
io_sethandler(0x03d0, 16,
vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr);
timer_add(&pcjr->timer, vid_poll, pcjr, 1);
cga_palette = 0;
cgapal_rebuild();
}

View File

@@ -2342,23 +2342,23 @@ pgc_cga_text(pgc_t *dev, int w)
int drawcursor = 0;
uint32_t cols[2];
int pitch = (dev->mapram[0x3e9] + 1) * 2;
uint16_t sc = (dev->displine & 0x0f) % pitch;
uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff;
uint16_t ca = (dev->mapram[0x3ef] | (dev->mapram[0x3ee] << 8)) & 0x3fff;
uint16_t scanline = (dev->displine & 0x0f) % pitch;
uint16_t memaddr = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff;
uint16_t cursoraddr = (dev->mapram[0x3ef] | (dev->mapram[0x3ee] << 8)) & 0x3fff;
const uint8_t *addr;
uint32_t val;
int cw = (w == 80) ? 8 : 16;
addr = &dev->cga_vram[((ma + ((dev->displine / pitch) * w)) * 2) & 0x3ffe];
ma += (dev->displine / pitch) * w;
addr = &dev->cga_vram[((memaddr + ((dev->displine / pitch) * w)) * 2) & 0x3ffe];
memaddr += (dev->displine / pitch) * w;
for (int x = 0; x < w; x++) {
chr = *addr++;
attr = *addr++;
/* Cursor enabled? */
if (ma == ca && (dev->cgablink & 8) && (dev->mapram[0x3ea] & 0x60) != 0x20) {
drawcursor = ((dev->mapram[0x3ea] & 0x1f) <= (sc >> 1)) && ((dev->mapram[0x3eb] & 0x1f) >= (sc >> 1));
if (memaddr == cursoraddr && (dev->cgablink & 8) && (dev->mapram[0x3ea] & 0x60) != 0x20) {
drawcursor = ((dev->mapram[0x3ea] & 0x1f) <= (scanline >> 1)) && ((dev->mapram[0x3eb] & 0x1f) >= (scanline >> 1));
} else
drawcursor = 0;
@@ -2374,9 +2374,9 @@ pgc_cga_text(pgc_t *dev, int w)
for (int c = 0; c < cw; c++) {
if (drawcursor)
val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f;
val = cols[(fontdatm[chr + dev->fontbase][scanline] & (1 << (c ^ 7))) ? 1 : 0] ^ 0x0f;
else
val = cols[(fontdatm[chr + dev->fontbase][sc] & (1 << (c ^ 7))) ? 1 : 0];
val = cols[(fontdatm[chr + dev->fontbase][scanline] & (1 << (c ^ 7))) ? 1 : 0];
if (cw == 8) /* 80x25 CGA text screen. */
buffer32->line[dev->displine][(x * cw) + c] = val;
else { /* 40x25 CGA text screen. */
@@ -2385,7 +2385,7 @@ pgc_cga_text(pgc_t *dev, int w)
}
}
ma++;
memaddr++;
}
}
@@ -2395,7 +2395,7 @@ pgc_cga_gfx40(pgc_t *dev)
{
uint32_t cols[4];
int col;
uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff;
uint16_t memaddr = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff;
const uint8_t *addr;
uint16_t dat;
@@ -2422,9 +2422,9 @@ pgc_cga_gfx40(pgc_t *dev)
}
for (uint8_t x = 0; x < 40; x++) {
addr = &dev->cga_vram[(ma + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff];
addr = &dev->cga_vram[(memaddr + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff];
dat = (addr[0] << 8) | addr[1];
dev->ma++;
dev->memaddr++;
for (uint8_t c = 0; c < 8; c++) {
buffer32->line[dev->displine][(x << 4) + (c << 1)] = buffer32->line[dev->displine][(x << 4) + (c << 1) + 1] = cols[dat >> 14];
dat <<= 2;
@@ -2437,7 +2437,7 @@ void
pgc_cga_gfx80(pgc_t *dev)
{
uint32_t cols[2];
uint16_t ma = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff;
uint16_t memaddr = (dev->mapram[0x3ed] | (dev->mapram[0x3ec] << 8)) & 0x3fff;
const uint8_t *addr;
uint16_t dat;
@@ -2445,9 +2445,9 @@ pgc_cga_gfx80(pgc_t *dev)
cols[1] = (dev->mapram[0x3d9] & 15) + 16;
for (uint8_t x = 0; x < 40; x++) {
addr = &dev->cga_vram[(ma + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff];
addr = &dev->cga_vram[(memaddr + 2 * x + 80 * (dev->displine >> 2) + 0x2000 * ((dev->displine >> 1) & 1)) & 0x3fff];
dat = (addr[0] << 8) | addr[1];
dev->ma++;
dev->memaddr++;
for (uint8_t c = 0; c < 16; c++) {
buffer32->line[dev->displine][(x << 4) + c] = cols[dat >> 15];
dat <<= 1;

View File

@@ -349,7 +349,7 @@ typedef struct da2_t {
int lowres;
int rowcount;
double clock;
uint32_t ma_latch, ca_adj;
uint32_t memaddr_latch, ca_adj;
uint64_t dispontime, dispofftime;
pc_timer_t timer;
@@ -358,11 +358,11 @@ typedef struct da2_t {
int dispon;
int hdisp_on;
uint32_t ma, maback, ca;
uint32_t memaddr, memaddr_backup, cursoraddr;
int vc;
int sc;
int scanline;
int linepos, vslines, linecountff;
int con, cursoron, blink, blinkconf;
int cursorvisible, cursoron, blink, blinkconf;
int scrollcache;
int char_width;
@@ -1960,10 +1960,10 @@ da2_render_text(da2_t *da2)
uint32_t chr_dbcs;
int chr_wide = 0;
int colormode = ((da2->attrc[LV_PAS_STATUS_CNTRL] & 0x80) == 0x80);
// da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc);
// da2_log("\nda2ma: %x, da2sc: %x\n", da2->memaddr, da2->scanline);
for (x = 0; x < da2->hdisp; x += 13) {
chr = da2->cram[(da2->ma) & DA2_MASK_CRAM];
attr = da2->cram[(da2->ma + 1) & DA2_MASK_CRAM];
chr = da2->cram[(da2->memaddr) & DA2_MASK_CRAM];
attr = da2->cram[(da2->memaddr + 1) & DA2_MASK_CRAM];
// if(chr!=0x20) da2_log("chr: %x, attr: %x ", chr, attr);
if (colormode) /* IO 3E8h, Index 1Dh */
{ /* --Parse attribute byte in color mode-- */
@@ -2003,11 +2003,11 @@ da2_render_text(da2_t *da2)
/* Stay drawing If the char code is DBCS and not at last column. */
if (chr_wide) {
/* Get high DBCS code from the next video address */
chr_dbcs = da2->cram[(da2->ma + 2) & DA2_MASK_CRAM];
chr_dbcs = da2->cram[(da2->memaddr + 2) & DA2_MASK_CRAM];
chr_dbcs <<= 8;
chr_dbcs |= chr;
/* Get the font pattern */
uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2);
uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->scanline, da2);
/* Draw 13 dots */
for (uint32_t n = 0; n < 13; n++) {
p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]];
@@ -2020,10 +2020,10 @@ da2_render_text(da2_t *da2)
fontbase = DA2_GAIJIRAM_SBEX;
else
fontbase = DA2_GAIJIRAM_SBCS;
uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2]; /* w13xh29 font */
uint16_t font = da2->mmio.ram[fontbase + chr * 0x40 + da2->scanline * 2]; /* w13xh29 font */
font <<= 8;
font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */
// if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font);
font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->scanline * 2 + 1]; /* w13xh29 font */
// if(chr!=0x20) da2_log("memaddr: %x, scanline: %x, chr: %x, font: %x ", da2->memaddr, da2->scanline, chr, font);
/* Draw 13 dots */
for (uint32_t n = 0; n < 13; n++) {
p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]];
@@ -2033,7 +2033,7 @@ da2_render_text(da2_t *da2)
}
/* right half of DBCS */
else {
uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2);
uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->scanline, da2);
/* Draw 13 dots */
for (uint32_t n = 0; n < 13; n++) {
p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]];
@@ -2042,7 +2042,7 @@ da2_render_text(da2_t *da2)
chr_wide = 0;
}
/* Line 28 (Underscore) Note: Draw this first to display blink + vertical + underline correctly. */
if (da2->sc == da2->crtc[LC_UNDERLINE_LOCATION] && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */
if (da2->scanline == da2->crtc[LC_UNDERLINE_LOCATION] && attr & 0x40 && !colormode) { /* Underscore only in monochrome mode */
for (uint32_t n = 0; n < 13; n++)
p[n] = da2->pallook[da2->egapal[fg]]; /* under line (white) */
}
@@ -2050,13 +2050,13 @@ da2_render_text(da2_t *da2)
if (attr & 0x10) {
p[0] = da2->pallook[da2->egapal[(colormode) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* vertical line (white) */
}
if (da2->sc == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) { /* HGrid */
if (da2->scanline == 0 && attr & 0x20 && ~da2->attrc[LV_PAS_STATUS_CNTRL]) { /* HGrid */
for (uint32_t n = 0; n < 13; n++)
p[n] = da2->pallook[da2->egapal[(colormode) ? IRGBtoBGRI(da2->attrc[LV_GRID_COLOR_0]) : 2]]; /* horizontal line (white) */
}
/* Drawing text cursor */
drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron);
if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) {
drawcursor = ((da2->memaddr == da2->cursoraddr) && da2->cursorvisible && da2->cursoron);
if (drawcursor && da2->scanline >= da2->crtc[LC_CURSOR_ROW_START] && da2->scanline <= da2->crtc[LC_CURSOR_ROW_END]) {
int cursorwidth = (da2->crtc[LC_COMPATIBILITY] & 0x20 ? 26 : 13);
int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[LV_CURSOR_COLOR]) : 2; /* Choose color 2 if mode 8 */
fg = (colormode) ? getPS55ForeColor(attr, da2) : ((attr & 0x08) ? 3 : 2);
@@ -2071,10 +2071,10 @@ da2_render_text(da2_t *da2)
else
p[n] = (p[n] == da2->pallook[da2->egapal[bg]]) ? da2->pallook[da2->egapal[cursorcolor]] : p[n];
}
da2->ma += 2;
da2->memaddr += 2;
p += 13;
}
// da2->ma &= DA2_MASK_CRAM;
// da2->memaddr &= DA2_MASK_CRAM;
// da2->writelines++;
}
}
@@ -2096,12 +2096,12 @@ da2_render_textm3(da2_t *da2)
int fg, bg;
uint32_t chr_dbcs;
int chr_wide = 0;
// da2_log("\nda2ma: %x, da2sc: %x\n", da2->ma, da2->sc);
// da2_log("\nda2ma: %x, da2sc: %x\n", da2->memaddr, da2->scanline);
for (x = 0; x < da2->hdisp; x += 13) {
chr = da2_vram_r(DA2_VM03_BASECHR + da2->ma, da2);
attr = da2_vram_r(DA2_VM03_BASECHR + da2->ma + 1, da2);
extattr = da2_vram_r(DA2_VM03_BASEEXATTR + da2->ma + 1, da2);
// if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->ma << 1) & da2->vram_mask, chr, attr);
chr = da2_vram_r(DA2_VM03_BASECHR + da2->memaddr, da2);
attr = da2_vram_r(DA2_VM03_BASECHR + da2->memaddr + 1, da2);
extattr = da2_vram_r(DA2_VM03_BASEEXATTR + da2->memaddr + 1, da2);
// if(chr!=0x20) da2_log("addr: %x, chr: %x, attr: %x ", (DA2_VM03_BASECHR + da2->memaddr << 1) & da2->vram_mask, chr, attr);
bg = attr >> 4;
// if (da2->blink) bg &= ~0x8;
// fg = (da2->blink || (!(attr & 0x80))) ? (attr & 0xf) : bg;
@@ -2118,11 +2118,11 @@ da2_render_textm3(da2_t *da2)
/* Stay drawing if the char code is DBCS and not at last column. */
if (chr_wide) {
/* Get high DBCS code from the next video address */
chr_dbcs = da2_vram_r(DA2_VM03_BASECHR + da2->ma + 2, da2);
chr_dbcs = da2_vram_r(DA2_VM03_BASECHR + da2->memaddr + 2, da2);
chr_dbcs <<= 8;
chr_dbcs |= chr;
/* Get the font pattern */
uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2);
uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->scanline, da2);
/* Draw 13 dots */
for (uint32_t n = 0; n < 13; n++) {
p[n] = da2->pallook[da2->egapal[(font & 0x80000000) ? fg : bg]];
@@ -2135,10 +2135,10 @@ da2_render_textm3(da2_t *da2)
fontbase = DA2_GAIJIRAM_SBEX;
else
fontbase = DA2_GAIJIRAM_SBCS;
uint16_t font = da2->mmio.ram[fontbase+ chr * 0x40 + da2->sc * 2]; /* w13xh29 font */
uint16_t font = da2->mmio.ram[fontbase+ chr * 0x40 + da2->scanline * 2]; /* w13xh29 font */
font <<= 8;
font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->sc * 2 + 1]; /* w13xh29 font */
// if(chr!=0x20) da2_log("ma: %x, sc: %x, chr: %x, font: %x ", da2->ma, da2->sc, chr, font);
font |= da2->mmio.ram[fontbase + chr * 0x40 + da2->scanline * 2 + 1]; /* w13xh29 font */
// if(chr!=0x20) da2_log("memaddr: %x, scanline: %x, chr: %x, font: %x ", da2->memaddr, da2->scanline, chr, font);
for (uint32_t n = 0; n < 13; n++) {
p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]];
font <<= 1;
@@ -2147,7 +2147,7 @@ da2_render_textm3(da2_t *da2)
}
/* right half of DBCS */
else {
uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->sc, da2);
uint32_t font = getfont_ps55dbcs(chr_dbcs, da2->scanline, da2);
/* Draw 13 dots */
for (uint32_t n = 0; n < 13; n++) {
p[n] = da2->pallook[da2->egapal[(font & 0x8000) ? fg : bg]];
@@ -2155,8 +2155,8 @@ da2_render_textm3(da2_t *da2)
}
chr_wide = 0;
}
drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron);
if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= da2->crtc[LC_CURSOR_ROW_END]) {
drawcursor = ((da2->memaddr == da2->cursoraddr) && da2->cursorvisible && da2->cursoron);
if (drawcursor && da2->scanline >= da2->crtc[LC_CURSOR_ROW_START] && da2->scanline <= da2->crtc[LC_CURSOR_ROW_END]) {
// int cursorwidth = (da2->crtc[0x1f] & 0x20 ? 26 : 13);
// int cursorcolor = (colormode) ? IRGBtoBGRI(da2->attrc[0x1a]) : 2;/* Choose color 2 if mode 8 */
// fg = (colormode) ? getPS55ForeColor(attr, da2) : (attr & 0x08) ? 3 : 2;
@@ -2168,10 +2168,10 @@ da2_render_textm3(da2_t *da2)
for (uint32_t n = 0; n < 13; n++)
p[n] = da2->pallook[da2->egapal[fg]];
}
da2->ma += 2;
da2->memaddr += 2;
p += 13;
}
// da2->ma &= DA2_MASK_CRAM;
// da2->memaddr &= DA2_MASK_CRAM;
// da2->writelines++;
}
}
@@ -2179,8 +2179,8 @@ da2_render_textm3(da2_t *da2)
static void
da2_render_color_4bpp(da2_t *da2)
{
int changed_offset = da2->ma >> 9;
// da2_log("ma %x cf %x\n", da2->ma, changed_offset);
int changed_offset = da2->memaddr >> 9;
// da2_log("memaddr %x cf %x\n", da2->memaddr, changed_offset);
da2->plane_mask &= 0x0f; /*safety */
if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) {
@@ -2191,7 +2191,7 @@ da2_render_color_4bpp(da2_t *da2)
if (da2->firstline_draw == 2000)
da2->firstline_draw = da2->displine;
da2->lastline_draw = da2->displine;
// da2_log("d %X\n", da2->ma);
// da2_log("d %X\n", da2->memaddr);
for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */
{
@@ -2199,9 +2199,9 @@ da2_render_color_4bpp(da2_t *da2)
uint8_t dat;
/* get 8 pixels from vram */
da2->ma &= da2->vram_display_mask;
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->ma << 3]);
da2->ma += 1;
da2->memaddr &= da2->vram_display_mask;
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->memaddr << 3]);
da2->memaddr += 1;
dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3));
p[0] = da2->pallook[da2->egapal[dat & da2->plane_mask]];
@@ -2228,8 +2228,8 @@ da2_render_color_4bpp(da2_t *da2)
static void
da2_render_color_8bpp(da2_t *da2)
{
int changed_offset = da2->ma >> 9;
// da2_log("ma %x cf %x\n", da2->ma, changed_offset);
int changed_offset = da2->memaddr >> 9;
// da2_log("memaddr %x cf %x\n", da2->memaddr, changed_offset);
if (da2->changedvram[changed_offset] || da2->changedvram[changed_offset + 1] || da2->fullchange) {
int x;
@@ -2239,7 +2239,7 @@ da2_render_color_8bpp(da2_t *da2)
if (da2->firstline_draw == 2000)
da2->firstline_draw = da2->displine;
da2->lastline_draw = da2->displine;
// da2_log("d %X\n", da2->ma);
// da2_log("d %X\n", da2->memaddr);
for (x = 0; x <= da2->hdisp; x += 8) /* hdisp = 1024 */
{
@@ -2247,10 +2247,10 @@ da2_render_color_8bpp(da2_t *da2)
uint8_t dat;
/* get 8 pixels from vram */
da2->ma &= da2->vram_display_mask;
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->ma << 3]);
*(uint32_t *) (&edat[4]) = *(uint32_t *) (&da2->vram[(da2->ma << 3) + 4]);
da2->ma += 1;
da2->memaddr &= da2->vram_display_mask;
*(uint32_t *) (&edat[0]) = *(uint32_t *) (&da2->vram[da2->memaddr << 3]);
*(uint32_t *) (&edat[4]) = *(uint32_t *) (&da2->vram[(da2->memaddr << 3) + 4]);
da2->memaddr += 1;
dat = ((edat[0] >> 7) & (1 << 0)) | ((edat[1] >> 6) & (1 << 1)) | ((edat[2] >> 5) & (1 << 2)) | ((edat[3] >> 4) & (1 << 3)) | ((edat[4] >> 3) & (1 << 4)) | ((edat[5] >> 2) & (1 << 5)) | ((edat[6] >> 1) & (1 << 6)) | ((edat[7] >> 0) & (1 << 7));
p[0] = da2->pallook[dat];
@@ -2343,9 +2343,9 @@ da2_recalctimings(da2_t *da2)
if (da2->rowoffset == 0)
da2->rowoffset = 64 * 2; /* To avoid causing a DBZ error */
if (da2->split == 0) /* To avoid a glitch in MODE 1 of OS/2 J1.3 DOSBox. */
da2->ma_latch = 0;
da2->memaddr_latch = 0;
else
da2->ma_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW];
da2->memaddr_latch = ((da2->crtc[LC_START_ADDRESS_HIGH] & 0x3ff) << 8) | da2->crtc[LC_START_ADDRESS_LOW];
da2->ca_adj = 0;
da2->rowcount = da2->crtc[LC_MAXIMUM_SCAN_LINE];
@@ -3022,7 +3022,7 @@ da2_poll(void *priv)
if (da2->dispon) {
da2->hdisp_on = 1;
da2->ma &= da2->vram_display_mask;
da2->memaddr &= da2->vram_display_mask;
if (da2->firstline == 2000) {
da2->firstline = da2->displine;
video_wait_for_buffer();
@@ -3035,7 +3035,7 @@ da2_poll(void *priv)
da2->lastline = da2->displine;
}
// da2_log("%03i %06X %06X\n", da2->displine, da2->ma,da2->vram_display_mask);
// da2_log("%03i %06X %06X\n", da2->displine, da2->memaddr,da2->vram_display_mask);
da2->displine++;
if ((da2->cgastat & 8) && ((da2->displine & 0xf) == (da2->crtc[LC_VERTICAL_SYNC_END] & 0xf)) && da2->vslines) {
// da2_log("Vsync off at line %i\n",displine);
@@ -3045,9 +3045,9 @@ da2_poll(void *priv)
if (da2->displine > 1200)
da2->displine = 0;
// da2_log("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322],
// displine, vc, ma);
// displine, vc, memaddr);
} else {
// da2_log("VC %i ma %05X\n", da2->vc, da2->ma);
// da2_log("VC %i memaddr %05X\n", da2->vc, da2->memaddr);
timer_advance_u64(&da2->timer, da2->dispontime);
if (da2->dispon)
@@ -3055,20 +3055,20 @@ da2_poll(void *priv)
da2->hdisp_on = 0;
da2->linepos = 0;
if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31))
da2->con = 0;
if (da2->scanline == (da2->crtc[LC_CURSOR_ROW_END] & 31))
da2->cursorvisible = 0;
if (da2->dispon) {
if (da2->sc == da2->rowcount) {
if (da2->scanline == da2->rowcount) {
da2->linecountff = 0;
da2->sc = 0;
da2->scanline = 0;
da2->maback += (da2->rowoffset << 1); /* color = 0x50(80), mono = 0x40(64) */
da2->maback &= da2->vram_display_mask;
da2->ma = da2->maback;
da2->memaddr_backup += (da2->rowoffset << 1); /* color = 0x50(80), mono = 0x40(64) */
da2->memaddr_backup &= da2->vram_display_mask;
da2->memaddr = da2->memaddr_backup;
} else {
da2->sc++;
da2->sc &= 31;
da2->ma = da2->maback;
da2->scanline++;
da2->scanline &= 31;
da2->memaddr = da2->memaddr_backup;
}
}
@@ -3076,9 +3076,9 @@ da2_poll(void *priv)
da2->vc &= 2047;
if (da2->vc == da2->split) {
// da2->ma = da2->maback = da2->hblank_sub;
da2->ma = da2->maback = 0;
da2->sc = 0;
// da2->memaddr = da2->memaddr_backup = da2->hblank_sub;
da2->memaddr = da2->memaddr_backup = 0;
da2->scanline = 0;
// da2->displine = 0;
}
@@ -3128,24 +3128,24 @@ da2_poll(void *priv)
changeframecount = 2;
da2->vslines = 0;
da2->ma
= da2->maback = da2->ma_latch << 1;
da2->ca = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj;
da2->ca <<= 1;
da2->memaddr
= da2->memaddr_backup = da2->memaddr_latch << 1;
da2->cursoraddr = ((da2->crtc[LC_CURSOR_LOC_HIGH] << 8) | da2->crtc[LC_CURSOR_LOC_LOWJ]) + da2->ca_adj;
da2->cursoraddr <<= 1;
// da2_log("Addr %08X vson %03X vsoff %01X\n",da2->ma,da2->vsyncstart,da2->crtc[0x11]&0xF);
// da2_log("Addr %08X vson %03X vsoff %01X\n",da2->memaddr,da2->vsyncstart,da2->crtc[0x11]&0xF);
}
if (da2->vc == da2->vtotal) {
// da2_log("VC vtotal\n");
// printf("Frame over at line %i %i %i %i\n",displine,vc,da2_vsyncstart,da2_dispend);
da2->vc = 0;
da2->sc = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f;
da2->scanline = da2->crtc[LC_PRESET_ROW_SCANJ] & 0x1f;
da2->dispon = 1;
da2->displine = 0;
da2->scrollcache = da2->attrc[LV_PANNING] & 7;
}
if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31))
da2->con = 1;
if (da2->scanline == (da2->crtc[LC_CURSOR_ROW_START] & 31))
da2->cursorvisible = 1;
}
}
@@ -3231,7 +3231,7 @@ da2_reset(void *priv)
da2->attrc[LV_CURSOR_COLOR] = 0x0f; /* cursor color */
da2->crtc[LC_HORIZONTAL_TOTAL] = 63; /* Horizontal Total */
da2->crtc[LC_VERTICAL_TOTALJ] = 255; /* Vertical Total (These two must be set before the timer starts.) */
da2->ma_latch = 0;
da2->memaddr_latch = 0;
da2->attrc[LV_CURSOR_CONTROL] = 0x13; /* cursor options */
da2->attr_palette_enable = 0; /* disable attribute generator */
@@ -3441,7 +3441,7 @@ static const device_config_t da2_configuration[] = {
// clang-format off
{
.name = "charset",
.description = "Charset",
.description = "Character set",
.type = CONFIG_SELECTION,
.default_int = DA2_DCONFIG_CHARSET_JPAN,
.selection = {

View File

@@ -180,7 +180,7 @@ rtg_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
@@ -211,7 +211,7 @@ rtg_recalctimings(svga_t *svga)
{
const rtg_t *dev = (rtg_t *) svga->priv;
svga->ma_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17);
svga->memaddr_latch |= ((svga->crtc[0x19] & 0x10) << 16) | ((svga->crtc[0x19] & 0x40) << 17);
svga->interlace = (svga->crtc[0x19] & 1);

View File

@@ -3179,9 +3179,9 @@ s3_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
if ((((svga->crtc[0x67] & 0xc) != 0xc) && (s3->chip >= S3_TRIO64V)) || (s3->chip < S3_TRIO64V))
svga->ma_latch |= (s3->ma_ext << 16);
svga->memaddr_latch |= (s3->ma_ext << 16);
} else {
svga->fullchange = svga->monitor->mon_changeframecount;
svga_recalctimings(svga);
@@ -3503,7 +3503,7 @@ s3_recalctimings(svga_t *svga)
}
svga->hdisp = svga->hdisp_old;
svga->ma_latch |= (s3->ma_ext << 16);
svga->memaddr_latch |= (s3->ma_ext << 16);
svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10));
@@ -4379,7 +4379,7 @@ s3_trio64v_recalctimings(svga_t *svga)
if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/
{
svga->ma_latch |= (s3->ma_ext << 16);
svga->memaddr_latch |= (s3->ma_ext << 16);
if (svga->crtc[0x51] & 0x30)
svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4;
else if (svga->crtc[0x43] & 0x04)
@@ -4427,9 +4427,9 @@ s3_trio64v_recalctimings(svga_t *svga)
} else /*Streams mode*/
{
if (s3->streams.buffer_ctrl & 1)
svga->ma_latch = s3->streams.pri_fb1 >> 2;
svga->memaddr_latch = s3->streams.pri_fb1 >> 2;
else
svga->ma_latch = s3->streams.pri_fb0 >> 2;
svga->memaddr_latch = s3->streams.pri_fb0 >> 2;
svga->hdisp = s3->streams.pri_w + 1;
if (s3->streams.pri_h < svga->dispend)

View File

@@ -688,10 +688,10 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv)
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) +
svga->memaddr_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) +
((svga->crtc[8] & 0x60) >> 5);
if ((svga->crtc[0x67] & 0xc) != 0xc)
svga->ma_latch |= (virge->ma_ext << 16);
svga->memaddr_latch |= (virge->ma_ext << 16);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
@@ -890,7 +890,7 @@ s3_virge_recalctimings(svga_t *svga)
}
if ((svga->crtc[0x67] & 0xc) != 0xc) { /*VGA mode*/
svga->ma_latch |= (virge->ma_ext << 16);
svga->memaddr_latch |= (virge->ma_ext << 16);
if (svga->crtc[0x51] & 0x30)
svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4;
else if (svga->crtc[0x43] & 0x04)
@@ -935,9 +935,9 @@ s3_virge_recalctimings(svga_t *svga)
} else { /*Streams mode*/
if (virge->chip < S3_VIRGEGX2) {
if (virge->streams.buffer_ctrl & 1)
svga->ma_latch = virge->streams.pri_fb1 >> 2;
svga->memaddr_latch = virge->streams.pri_fb1 >> 2;
else
svga->ma_latch = virge->streams.pri_fb0 >> 2;
svga->memaddr_latch = virge->streams.pri_fb0 >> 2;
svga->hdisp = virge->streams.pri_w + 1;
if (virge->streams.pri_h < svga->dispend)
@@ -946,7 +946,7 @@ s3_virge_recalctimings(svga_t *svga)
svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x;
svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y;
} else {
svga->ma_latch |= (virge->ma_ext << 16);
svga->memaddr_latch |= (virge->ma_ext << 16);
if (svga->crtc[0x51] & 0x30)
svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4;
else if (svga->crtc[0x43] & 0x04)

Some files were not shown because too many files have changed in this diff Show More