mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 01:48:21 -07:00
Merge pull request #5674 from starfrost013/bugfixes
Video Refactor Part 2: Super CGA
This commit is contained in:
72
src/include/86box/m_pcjr.h
Normal file
72
src/include/86box/m_pcjr.h
Normal 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 stat;
|
||||
int addr_mode;
|
||||
uint8_t *vram;
|
||||
uint8_t *b8000;
|
||||
int linepos;
|
||||
int displine;
|
||||
int sc;
|
||||
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 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;
|
||||
|
||||
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);
|
||||
95
src/include/86box/m_tandy.h
Normal file
95
src/include/86box/m_tandy.h
Normal 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 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 cursorvisible;
|
||||
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;
|
||||
|
||||
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
|
||||
@@ -11,7 +11,8 @@
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -56,6 +57,7 @@ typedef enum cga_crtc_registers_e
|
||||
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,
|
||||
@@ -88,7 +90,7 @@ typedef struct cga_t {
|
||||
int sc;
|
||||
int vc;
|
||||
int cgadispon;
|
||||
int con;
|
||||
int cursorvisible; // Determines if the cursor is visible FOR THE CURRENT SCANLINE.
|
||||
int cursoron;
|
||||
int cgablink;
|
||||
int vsynctime;
|
||||
|
||||
@@ -68,7 +68,7 @@ typedef struct ega_t {
|
||||
int chain4;
|
||||
int chain2_read;
|
||||
int chain2_write;
|
||||
int con;
|
||||
int cursorvisible;
|
||||
int oddeven_page;
|
||||
int oddeven_chain;
|
||||
int vc;
|
||||
@@ -193,7 +193,7 @@ extern int sc;
|
||||
|
||||
extern uint32_t ma;
|
||||
extern uint32_t ca;
|
||||
extern int con;
|
||||
extern int cursorvisible;
|
||||
extern int cursoron;
|
||||
extern int cgablink;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ typedef struct {
|
||||
int sc;
|
||||
uint16_t ma;
|
||||
uint16_t maback;
|
||||
int con;
|
||||
int cursorvisible;
|
||||
int cursoron;
|
||||
int dispon;
|
||||
int blink;
|
||||
|
||||
@@ -28,7 +28,7 @@ typedef struct mda_t {
|
||||
int sc;
|
||||
uint16_t ma;
|
||||
uint16_t maback;
|
||||
int con;
|
||||
int cursorvisible;
|
||||
int cursoron;
|
||||
int dispon;
|
||||
int blink;
|
||||
|
||||
@@ -115,7 +115,7 @@ typedef struct pgc {
|
||||
int displine;
|
||||
int vc;
|
||||
int cgadispon;
|
||||
int con;
|
||||
int cursorvisible;
|
||||
int cursoron;
|
||||
int cgablink;
|
||||
int vsynctime;
|
||||
|
||||
@@ -105,7 +105,7 @@ typedef struct svga_t {
|
||||
int vslines;
|
||||
int linecountff;
|
||||
int oddeven;
|
||||
int con;
|
||||
int cursorvisible;
|
||||
int cursoron;
|
||||
int blink;
|
||||
int scrollcache;
|
||||
|
||||
@@ -27,7 +27,7 @@ extern int sc;
|
||||
|
||||
extern uint32_t ma;
|
||||
extern uint32_t ca;
|
||||
extern int con;
|
||||
extern int cursorvisible;
|
||||
extern int cursoron;
|
||||
extern int cgablink;
|
||||
|
||||
|
||||
@@ -395,6 +395,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 +610,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*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -116,7 +116,7 @@ typedef struct amsvid_t {
|
||||
int sc;
|
||||
int vc;
|
||||
int cgadispon;
|
||||
int con;
|
||||
int cursorvisible;
|
||||
int cursoron;
|
||||
int cgablink;
|
||||
int vsynctime;
|
||||
@@ -369,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) {
|
||||
drawcursor = ((vid->ma == ca) && 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)
|
||||
@@ -408,12 +408,12 @@ vid_poll_1512(void *priv)
|
||||
}
|
||||
vid->ma++;
|
||||
}
|
||||
} 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) {
|
||||
drawcursor = ((vid->ma == ca) && 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))
|
||||
@@ -433,10 +433,10 @@ vid_poll_1512(void *priv)
|
||||
}
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
@@ -477,7 +477,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 {
|
||||
@@ -486,7 +486,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;
|
||||
@@ -513,7 +513,7 @@ vid_poll_1512(void *priv)
|
||||
vid->stat &= ~8;
|
||||
}
|
||||
if (vid->sc == (vid->crtc[11] & 31)) {
|
||||
vid->con = 0;
|
||||
vid->cursorvisible = 0;
|
||||
}
|
||||
if (vid->vadj) {
|
||||
vid->sc++;
|
||||
@@ -545,7 +545,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;
|
||||
@@ -582,15 +582,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 {
|
||||
@@ -607,7 +607,7 @@ vid_poll_1512(void *priv)
|
||||
vid->ma = vid->maback;
|
||||
}
|
||||
if (vid->sc == (vid->crtc[10] & 31))
|
||||
vid->con = 1;
|
||||
vid->cursorvisible = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1292,7 +1292,7 @@ lcdm_poll(amsvid_t *vid)
|
||||
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);
|
||||
drawcursor = ((mda->ma == ca) && mda->cursorvisible && mda->cursoron);
|
||||
blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
|
||||
|
||||
lcd_draw_char_80(vid, &(buffer32->line[mda->displine])[x * 8], chr, attr, drawcursor, blink, mda->sc, 0, mda->ctrl);
|
||||
@@ -1316,7 +1316,7 @@ lcdm_poll(amsvid_t *vid)
|
||||
mda->stat &= ~8;
|
||||
}
|
||||
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) {
|
||||
mda->con = 0;
|
||||
mda->cursorvisible = 0;
|
||||
}
|
||||
if (mda->vadj) {
|
||||
mda->sc++;
|
||||
@@ -1383,7 +1383,7 @@ lcdm_poll(amsvid_t *vid)
|
||||
mda->ma = mda->maback;
|
||||
}
|
||||
if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1)))
|
||||
mda->con = 1;
|
||||
mda->cursorvisible = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1403,14 +1403,14 @@ lcdc_poll(amsvid_t *vid)
|
||||
uint16_t ca;
|
||||
int blink;
|
||||
|
||||
ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff;
|
||||
ca = (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)
|
||||
if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3)
|
||||
cga->sc = ((cga->sc << 1) + cga->oddeven) & 7;
|
||||
if (cga->cgadispon) {
|
||||
if (cga->displine < cga->firstline) {
|
||||
@@ -1419,28 +1419,28 @@ 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);
|
||||
drawcursor = ((cga->ma == ca) && 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->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++;
|
||||
}
|
||||
} else if (!(cga->cgamode & 2)) {
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
} else if (!(cga->cgamode & CGA_MODE_FLAG_GRAPHICS)) {
|
||||
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; 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);
|
||||
drawcursor = ((cga->ma == ca) && 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->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 { /* Graphics mode */
|
||||
for (x = 0; x < cga->crtc[1]; x++) {
|
||||
for (x = 0; x < cga->crtc[CGA_CRTC_HDISP]; 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 (uint8_t c = 0; c < 16; c++) {
|
||||
@@ -1450,22 +1450,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)
|
||||
if (cga->vc == cga->crtc[CGA_CRTC_VSYNC] && !cga->sc)
|
||||
cga->cgastat |= 8;
|
||||
cga->displine++;
|
||||
if (cga->displine >= 360)
|
||||
@@ -1478,10 +1478,10 @@ 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;
|
||||
if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
|
||||
cga->cursorvisible = 0;
|
||||
}
|
||||
if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1))
|
||||
if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
|
||||
cga->maback = cga->ma;
|
||||
if (cga->vadj) {
|
||||
cga->sc++;
|
||||
@@ -1490,41 +1490,41 @@ lcdc_poll(amsvid_t *vid)
|
||||
cga->vadj--;
|
||||
if (!cga->vadj) {
|
||||
cga->cgadispon = 1;
|
||||
cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff;
|
||||
cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
|
||||
cga->sc = 0;
|
||||
}
|
||||
} else if (cga->sc == cga->crtc[9]) {
|
||||
} else if (cga->sc == cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) {
|
||||
cga->maback = cga->ma;
|
||||
cga->sc = 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->ma = cga->maback = (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;
|
||||
@@ -1536,7 +1536,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);
|
||||
@@ -1553,15 +1553,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
|
||||
@@ -1579,10 +1579,10 @@ lcdc_poll(amsvid_t *vid)
|
||||
}
|
||||
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++)
|
||||
if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == ((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->ma << 1) + x) & 0x3fff];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,49 +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 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) */
|
||||
@@ -626,643 +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;
|
||||
}
|
||||
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)
|
||||
@@ -1433,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
|
||||
|
||||
@@ -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,79 +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 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
|
||||
@@ -655,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;
|
||||
@@ -690,762 +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;
|
||||
}
|
||||
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)
|
||||
@@ -1630,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 {
|
||||
@@ -1654,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;
|
||||
|
||||
@@ -1803,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;
|
||||
|
||||
@@ -1815,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;
|
||||
@@ -1828,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -1591,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
|
||||
},
|
||||
@@ -1630,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
|
||||
},
|
||||
@@ -2531,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
|
||||
},
|
||||
|
||||
@@ -11,20 +11,32 @@
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
#
|
||||
# Copyright 2020-2021 David Hrdlička.
|
||||
# Copyright 2025 starfrost
|
||||
#
|
||||
|
||||
add_library(vid OBJECT
|
||||
agpgart.c
|
||||
video.c
|
||||
vid_table.c
|
||||
# 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
|
||||
vid_hercules.c
|
||||
vid_herculesplus.c
|
||||
vid_incolor.c
|
||||
vid_colorplus.c
|
||||
vid_hercules_plus.c
|
||||
vid_hercules_incolor.c
|
||||
vid_genius.c
|
||||
vid_pgc.c
|
||||
vid_im1024.c
|
||||
@@ -70,9 +82,7 @@ add_library(vid OBJECT
|
||||
vid_s3.c vid_s3_virge.c
|
||||
vid_ibm_rgb528_ramdac.c
|
||||
vid_sdac_ramdac.c
|
||||
vid_ogc.c
|
||||
vid_mga.c
|
||||
vid_nga.c
|
||||
vid_tvp3026_ramdac.c
|
||||
vid_att2xc498_ramdac.c
|
||||
vid_xga.c
|
||||
|
||||
@@ -75,7 +75,7 @@ cga_update_latch(cga_t *cga)
|
||||
{
|
||||
uint32_t lp_latch = cga->displine * cga->crtc[CGA_CRTC_HDISP];
|
||||
|
||||
cga->crtc[0x10] = (lp_latch >> 8) & 0x3f;
|
||||
cga->crtc[CGA_CRTC_LIGHT_PEN_ADDR_HIGH] = (lp_latch >> 8) & 0x3f;
|
||||
cga->crtc[CGA_CRTC_LIGHT_PEN_ADDR_LOW] = lp_latch & 0xff;
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ cga_render(cga_t *cga, int line)
|
||||
attr = cga->charbuffer[(x << 1) + 1];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
|
||||
drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron);
|
||||
cols[1] = (attr & 15) + 16;
|
||||
if (cga->cgamode & CGA_MODE_FLAG_BLINK) {
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
@@ -310,14 +310,14 @@ cga_render(cga_t *cga, int line)
|
||||
}
|
||||
cga->ma++;
|
||||
}
|
||||
} else if (!(cga->cgamode & 2)) {
|
||||
} 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->ma << 1) & 0x3fff];
|
||||
attr = cga->vram[((cga->ma << 1) + 1) & 0x3fff];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron);
|
||||
drawcursor = ((cga->ma == ca) && cga->cursorvisible && cga->cursoron);
|
||||
cols[1] = (attr & 15) + 16;
|
||||
if (cga->cgamode & CGA_MODE_FLAG_BLINK) {
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
@@ -594,7 +594,7 @@ cga_poll(void *priv)
|
||||
}
|
||||
if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_END] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 &&
|
||||
cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_END] & 31) >> 1))) {
|
||||
cga->con = 0;
|
||||
cga->cursorvisible = 0;
|
||||
}
|
||||
if ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 && cga->sc == (cga->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
|
||||
cga->maback = cga->ma;
|
||||
@@ -625,6 +625,7 @@ cga_poll(void *priv)
|
||||
cga->cgadispon = 1;
|
||||
cga->ma = cga->maback = (cga->crtc[CGA_CRTC_START_ADDR_LOW] | (cga->crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
|
||||
}
|
||||
|
||||
switch (cga->crtc[CGA_CRTC_CURSOR_START] & 0x60) {
|
||||
case 0x20:
|
||||
cga->cursoron = 0;
|
||||
@@ -724,7 +725,7 @@ cga_poll(void *priv)
|
||||
cga->cgastat &= ~1;
|
||||
if (cga->sc == (cga->crtc[CGA_CRTC_CURSOR_START] & 31) || ((cga->crtc[CGA_CRTC_INTERLACE] & 3) == 3 &&
|
||||
cga->sc == ((cga->crtc[CGA_CRTC_CURSOR_START] & 31) >> 1)))
|
||||
cga->con = 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->ma << 1) + x) & 0x3fff];
|
||||
|
||||
@@ -37,16 +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 */
|
||||
|
||||
#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 };
|
||||
|
||||
@@ -57,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);
|
||||
@@ -147,7 +150,7 @@ colorplus_poll(void *priv)
|
||||
colorplus->cga.cgastat |= 1;
|
||||
colorplus->cga.linepos = 1;
|
||||
oldsc = colorplus->cga.sc;
|
||||
if ((colorplus->cga.crtc[8] & 3) == 3)
|
||||
if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3)
|
||||
colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7;
|
||||
if (colorplus->cga.cgadispon) {
|
||||
if (colorplus->cga.displine < colorplus->cga.firstline) {
|
||||
@@ -157,10 +160,10 @@ 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++) {
|
||||
for (x = 0; x < colorplus->cga.crtc[CGA_CRTC_HDISP]; 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++;
|
||||
@@ -173,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;
|
||||
@@ -186,7 +189,7 @@ colorplus_poll(void *priv)
|
||||
cols[2] = col | 4;
|
||||
cols[3] = col | 6;
|
||||
}
|
||||
for (x = 0; x < colorplus->cga.crtc[1]; x++) {
|
||||
for (x = 0; x < colorplus->cga.crtc[CGA_CRTC_HDISP]; 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++;
|
||||
@@ -200,10 +203,10 @@ 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]);
|
||||
@@ -211,7 +214,7 @@ colorplus_poll(void *priv)
|
||||
video_process_8(x, colorplus->cga.displine);
|
||||
|
||||
colorplus->cga.sc = oldsc;
|
||||
if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc)
|
||||
if (colorplus->cga.vc == colorplus->cga.crtc[CGA_CRTC_VSYNC] && !colorplus->cga.sc)
|
||||
colorplus->cga.cgastat |= 8;
|
||||
colorplus->cga.displine++;
|
||||
if (colorplus->cga.displine >= 360)
|
||||
@@ -224,10 +227,11 @@ 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;
|
||||
if (colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_CURSOR_END] & 31)
|
||||
|| ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == ((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))
|
||||
if ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
|
||||
colorplus->cga.maback = colorplus->cga.ma;
|
||||
if (colorplus->cga.vadj) {
|
||||
colorplus->cga.sc++;
|
||||
@@ -236,41 +240,41 @@ colorplus_poll(void *priv)
|
||||
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.ma = colorplus->cga.maback = (colorplus->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (colorplus->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
|
||||
colorplus->cga.sc = 0;
|
||||
}
|
||||
} else if (colorplus->cga.sc == colorplus->cga.crtc[9]) {
|
||||
} else if (colorplus->cga.sc == colorplus->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR]) {
|
||||
colorplus->cga.maback = colorplus->cga.ma;
|
||||
colorplus->cga.sc = 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.ma = colorplus->cga.maback = (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;
|
||||
@@ -287,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 {
|
||||
@@ -314,10 +318,10 @@ colorplus_poll(void *priv)
|
||||
}
|
||||
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++)
|
||||
if (colorplus->cga.sc == (colorplus->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((colorplus->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && colorplus->cga.sc == ((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.ma << 1) + x) & 0x3fff];
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -68,9 +68,9 @@ compaq_cga_recalctimings(cga_t *dev)
|
||||
double _dispontime;
|
||||
double _dispofftime;
|
||||
double disptime;
|
||||
disptime = dev->crtc[0] + 1;
|
||||
disptime = dev->crtc[CGA_CRTC_HTOTAL] + 1;
|
||||
|
||||
_dispontime = dev->crtc[1];
|
||||
_dispontime = dev->crtc[CGA_CRTC_HDISP];
|
||||
_dispofftime = disptime - _dispontime;
|
||||
_dispontime *= MDACONST;
|
||||
_dispofftime *= MDACONST;
|
||||
@@ -81,24 +81,26 @@ compaq_cga_recalctimings(cga_t *dev)
|
||||
static void
|
||||
compaq_cga_poll(void *priv)
|
||||
{
|
||||
cga_t *dev = (cga_t *) priv;
|
||||
uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
|
||||
int underline = 0;
|
||||
int blink = 0;
|
||||
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;
|
||||
cga_t *dev = (cga_t *) priv;
|
||||
uint16_t ca = (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 oldsc;
|
||||
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 & 0x12) || (dev->crtc[9] != 13)) {
|
||||
if ((dev->cgamode & highres_graphics_flag) || (dev->crtc[CGA_CRTC_MAX_SCANLINE_ADDR] != 13)) {
|
||||
overscan_x = overscan_y = 16;
|
||||
cga_poll(dev);
|
||||
return;
|
||||
@@ -111,7 +113,7 @@ compaq_cga_poll(void *priv)
|
||||
dev->cgastat |= 1;
|
||||
dev->linepos = 1;
|
||||
oldsc = dev->sc;
|
||||
if ((dev->crtc[8] & 3) == 3)
|
||||
if ((dev->crtc[CGA_CRTC_INTERLACE] & 3) == 3)
|
||||
dev->sc = ((dev->sc << 1) + dev->oddeven) & 7;
|
||||
if (dev->cgadispon) {
|
||||
if (dev->displine < dev->firstline) {
|
||||
@@ -125,21 +127,21 @@ compaq_cga_poll(void *priv)
|
||||
|
||||
for (c = 0; c < 8; c++) {
|
||||
buffer32->line[dev->displine][c] = cols[0];
|
||||
if (dev->cgamode & 1)
|
||||
buffer32->line[dev->displine][c + (dev->crtc[1] << 3) + 8] = 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[1] << 4) + 8] = cols[0];
|
||||
buffer32->line[dev->displine][c + (dev->crtc[CGA_CRTC_HDISP] << 4) + 8] = cols[0];
|
||||
}
|
||||
|
||||
if (dev->cgamode & 1) {
|
||||
for (x = 0; x < dev->crtc[1]; x++) {
|
||||
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->ma == ca) && dev->con && dev->cursoron);
|
||||
drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron);
|
||||
|
||||
if (vflags) {
|
||||
underline = 0;
|
||||
blink = ((dev->cgablink & 8) && (dev->cgamode & 0x20) && (attr & 0x80) && !drawcursor);
|
||||
blink = ((dev->cgablink & 8) && (dev->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
|
||||
}
|
||||
|
||||
if (vflags && (dev->cgamode & 0x80)) {
|
||||
@@ -148,7 +150,7 @@ compaq_cga_poll(void *priv)
|
||||
|
||||
if ((dev->sc == 12) && ((attr & 7) == 1))
|
||||
underline = 1;
|
||||
} else if (dev->cgamode & 0x20) {
|
||||
} else if (dev->cgamode & CGA_MODE_FLAG_BLINK) {
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
|
||||
@@ -179,14 +181,14 @@ compaq_cga_poll(void *priv)
|
||||
dev->ma++;
|
||||
}
|
||||
} else {
|
||||
for (x = 0; x < dev->crtc[1]; x++) {
|
||||
for (x = 0; x < dev->crtc[CGA_CRTC_HDISP]; x++) {
|
||||
chr = dev->vram[(dev->ma << 1) & 0x3fff];
|
||||
attr = dev->vram[((dev->ma << 1) + 1) & 0x3fff];
|
||||
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
|
||||
drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron);
|
||||
|
||||
if (vflags) {
|
||||
underline = 0;
|
||||
blink = ((dev->cgablink & 8) && (dev->cgamode & 0x20) && (attr & 0x80) && !drawcursor);
|
||||
blink = ((dev->cgablink & 8) && (dev->cgamode & CGA_MODE_FLAG_BLINK) && (attr & 0x80) && !drawcursor);
|
||||
}
|
||||
|
||||
if (vflags && (dev->cgamode & 0x80)) {
|
||||
@@ -194,7 +196,7 @@ compaq_cga_poll(void *priv)
|
||||
cols[1] = mdaattr[attr][blink][1];
|
||||
if (dev->sc == 12 && (attr & 7) == 1)
|
||||
underline = 1;
|
||||
} else if (dev->cgamode & 0x20) {
|
||||
} else if (dev->cgamode & CGA_MODE_FLAG_BLINK) {
|
||||
cols[1] = (attr & 15) + 16;
|
||||
cols[0] = ((attr >> 4) & 7) + 16;
|
||||
|
||||
@@ -231,19 +233,19 @@ compaq_cga_poll(void *priv)
|
||||
} else {
|
||||
cols[0] = (dev->cgacol & 15) + 16;
|
||||
|
||||
if (dev->cgamode & 1)
|
||||
hline(buffer32, 0, dev->displine, (dev->crtc[1] << 3) + 16, cols[0]);
|
||||
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[1] << 4) + 16, cols[0]);
|
||||
hline(buffer32, 0, dev->displine, (dev->crtc[CGA_CRTC_HDISP] << 4) + 16, cols[0]);
|
||||
}
|
||||
|
||||
if (dev->cgamode & 1)
|
||||
x = (dev->crtc[1] << 3) + 16;
|
||||
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES)
|
||||
x = (dev->crtc[CGA_CRTC_HDISP] << 3) + 16;
|
||||
else
|
||||
x = (dev->crtc[1] << 4) + 16;
|
||||
x = (dev->crtc[CGA_CRTC_HDISP] << 4) + 16;
|
||||
|
||||
if (dev->composite) {
|
||||
if (dev->cgamode & 0x10)
|
||||
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)
|
||||
border = 0x00;
|
||||
else
|
||||
border = dev->cgacol & 0x0f;
|
||||
@@ -256,7 +258,7 @@ compaq_cga_poll(void *priv)
|
||||
video_process_8(x, dev->displine);
|
||||
|
||||
dev->sc = oldsc;
|
||||
if (dev->vc == dev->crtc[7] && !dev->sc)
|
||||
if (dev->vc == dev->crtc[CGA_CRTC_VSYNC] && !dev->sc)
|
||||
dev->cgastat |= 8;
|
||||
dev->displine++;
|
||||
if (dev->displine >= 500)
|
||||
@@ -270,9 +272,8 @@ compaq_cga_poll(void *priv)
|
||||
dev->cgastat &= ~8;
|
||||
}
|
||||
|
||||
if (dev->sc == (dev->crtc[11] & 31) || (((dev->crtc[8] & 3) == 3) &&
|
||||
(dev->sc == ((dev->crtc[11] & 31) >> 1)))) {
|
||||
dev->con = 0;
|
||||
if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
|
||||
dev->cursorvisible = 0;
|
||||
}
|
||||
if ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))
|
||||
dev->maback = dev->ma;
|
||||
@@ -284,14 +285,14 @@ compaq_cga_poll(void *priv)
|
||||
if (!dev->vadj) {
|
||||
dev->cgadispon = 1;
|
||||
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
|
||||
dev->sc = 0;
|
||||
dev->sc = 0;
|
||||
}
|
||||
} else if (dev->sc == dev->crtc[9]) {
|
||||
dev->maback = dev->ma;
|
||||
dev->sc = 0;
|
||||
oldvc = dev->vc;
|
||||
oldvc = dev->vc;
|
||||
dev->vc++;
|
||||
dev->vc &= 127;
|
||||
dev->vc &= 127;
|
||||
|
||||
if (dev->vc == dev->crtc[6])
|
||||
dev->cgadispon = 0;
|
||||
@@ -321,10 +322,10 @@ compaq_cga_poll(void *priv)
|
||||
compaq_cga_log("Lastline %i Firstline %i %i\n", dev->lastline,
|
||||
dev->firstline, dev->lastline - dev->firstline);
|
||||
|
||||
if (dev->cgamode & 1)
|
||||
x = (dev->crtc[1] << 3) + 16;
|
||||
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES)
|
||||
x = (dev->crtc[CGA_CRTC_HDISP] << 3) + 16;
|
||||
else
|
||||
x = (dev->crtc[1] << 4) + 16;
|
||||
x = (dev->crtc[CGA_CRTC_HDISP] << 4) + 16;
|
||||
|
||||
dev->lastline++;
|
||||
|
||||
@@ -339,8 +340,7 @@ compaq_cga_poll(void *priv)
|
||||
if (!enable_overscan)
|
||||
xs_temp -= 16;
|
||||
|
||||
if ((dev->cgamode & 8) && ((xs_temp != xsize) ||
|
||||
(ys_temp != ysize) || video_force_resize_get())) {
|
||||
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));
|
||||
@@ -361,7 +361,7 @@ compaq_cga_poll(void *priv)
|
||||
if (enable_overscan)
|
||||
xsize -= 16;
|
||||
video_res_y = ysize;
|
||||
if (dev->cgamode & 1) {
|
||||
if (dev->cgamode & CGA_MODE_FLAG_HIGHRES) {
|
||||
video_res_x /= 8;
|
||||
video_res_y /= dev->crtc[9] + 1;
|
||||
video_bpp = 0;
|
||||
@@ -390,12 +390,11 @@ compaq_cga_poll(void *priv)
|
||||
if (dev->cgadispon)
|
||||
dev->cgastat &= ~1;
|
||||
|
||||
if (dev->sc == (dev->crtc[10] & 31) ||
|
||||
(((dev->crtc[8] & 3) == 3) && (dev->sc == ((dev->crtc[10] & 31) >> 1))))
|
||||
dev->con = 1;
|
||||
if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))
|
||||
dev->cursorvisible = 1;
|
||||
|
||||
if (dev->cgadispon && (dev->cgamode & 1)) {
|
||||
for (x = 0; x < (dev->crtc[1] << 1); x++)
|
||||
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->ma << 1) + x) & 0x3fff];
|
||||
}
|
||||
}
|
||||
@@ -475,8 +474,7 @@ compaq_cga_speed_changed(void *priv)
|
||||
{
|
||||
cga_t *dev = (cga_t *) priv;
|
||||
|
||||
if (dev->crtc[9] == 13)
|
||||
/* Character height */
|
||||
if (dev->crtc[9] == 13) /* Character height */
|
||||
compaq_cga_recalctimings(dev);
|
||||
else
|
||||
cga_recalctimings(dev);
|
||||
784
src/video/vid_cga_compaq_plasma.c
Normal file
784
src/video/vid_cga_compaq_plasma.c
Normal file
@@ -0,0 +1,784 @@
|
||||
/*
|
||||
* 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 & 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[CGA_CRTC_START_ADDR_LOW] | (self->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
|
||||
uint16_t ca = (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 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[CGA_CRTC_CURSOR_START] & 0x60) == 0x20)
|
||||
cursorline = 0;
|
||||
else
|
||||
cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 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 & 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) + 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[CGA_CRTC_CURSOR_START] & 0x60) == 0x20)
|
||||
cursorline = 0;
|
||||
else
|
||||
cursorline = (((self->cga.crtc[CGA_CRTC_CURSOR_START] & 0x0f) << 1) <= sc) && (((self->cga.crtc[CGA_CRTC_CURSOR_END] & 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 & 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) + 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 & 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 + ((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 & 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;
|
||||
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
|
||||
};
|
||||
@@ -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 ca = (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
|
||||
int drawcursor;
|
||||
int x;
|
||||
int c;
|
||||
@@ -164,7 +164,7 @@ nga_poll(void *priv)
|
||||
int oldsc;
|
||||
|
||||
/* 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;
|
||||
@@ -176,7 +176,7 @@ nga_poll(void *priv)
|
||||
nga->cga.linepos = 1;
|
||||
oldsc = nga->cga.sc;
|
||||
/* if interlaced */
|
||||
if ((nga->cga.crtc[8] & 3) == 3)
|
||||
if ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3)
|
||||
nga->cga.sc = ((nga->cga.sc << 1) + nga->cga.oddeven) & 7;
|
||||
if (nga->cga.cgadispon) {
|
||||
if (nga->cga.displine < nga->cga.firstline) {
|
||||
@@ -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.ma == ca) && 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) {
|
||||
@@ -224,20 +224,20 @@ nga_poll(void *priv)
|
||||
}
|
||||
}
|
||||
/* 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) {
|
||||
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.ma << 1) & 0x3fff) + nga->base];
|
||||
attr = nga->cga.vram[(((nga->cga.ma << 1) + 1) & 0x3fff) + nga->base];
|
||||
} else {
|
||||
chr = attr = 0;
|
||||
}
|
||||
drawcursor = ((nga->cga.ma == ca) && nga->cga.con && nga->cga.cursoron);
|
||||
drawcursor = ((nga->cga.ma == ca) && 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 */
|
||||
@@ -262,7 +262,7 @@ nga_poll(void *priv)
|
||||
/* 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,...)
|
||||
@@ -277,7 +277,7 @@ nga_poll(void *priv)
|
||||
} 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 */
|
||||
@@ -306,11 +306,11 @@ nga_poll(void *priv)
|
||||
}
|
||||
|
||||
/* 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];
|
||||
/* each pixel is represented by one bit, so draw 16 pixels at a time */
|
||||
@@ -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;
|
||||
/* 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.sc)
|
||||
nga->cga.cgastat |= 8;
|
||||
nga->cga.displine++;
|
||||
if (nga->cga.displine >= 720)
|
||||
@@ -380,7 +380,7 @@ nga_poll(void *priv)
|
||||
nga->lineff ^= 1;
|
||||
|
||||
/* text mode or 640x400x2 */
|
||||
if (nga->lineff && !((nga->cga.cgamode & 1) && (nga->cga.cgamode & 0x40))) {
|
||||
if (nga->lineff && !((nga->cga.cgamode & CGA_MODE_FLAG_HIGHRES) && (nga->cga.cgamode & 0x40))) {
|
||||
nga->cga.ma = nga->cga.maback;
|
||||
/* 640x400x4 */
|
||||
} else {
|
||||
@@ -390,11 +390,11 @@ 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;
|
||||
if (nga->cga.sc == (nga->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == ((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))
|
||||
if ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
|
||||
nga->cga.maback = nga->cga.ma;
|
||||
|
||||
if (nga->cga.vadj) {
|
||||
@@ -405,12 +405,12 @@ nga_poll(void *priv)
|
||||
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.ma = nga->cga.maback = (nga->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (nga->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
|
||||
nga->cga.sc = 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))) {
|
||||
} else if (nga->cga.sc == nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == (nga->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) {
|
||||
nga->cga.maback = nga->cga.ma;
|
||||
nga->cga.sc = 0;
|
||||
oldvc = nga->cga.vc;
|
||||
@@ -418,21 +418,21 @@ nga_poll(void *priv)
|
||||
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.ma = nga->cga.maback = (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;
|
||||
@@ -445,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;
|
||||
@@ -471,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));
|
||||
@@ -493,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;
|
||||
@@ -523,13 +523,13 @@ nga_poll(void *priv)
|
||||
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.sc == (nga->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((nga->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && nga->cga.sc == ((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++)
|
||||
for (x = 0; x < (nga->cga.crtc[CGA_CRTC_HDISP] << 1); x++)
|
||||
nga->cga.charbuffer[x] = nga->cga.vram[(((nga->cga.ma << 1) + x) & 0x3fff) + nga->base];
|
||||
}
|
||||
}
|
||||
@@ -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 ca = (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_CURSOR_ADDR_HIGH] << 8)) & 0x3fff;
|
||||
int drawcursor;
|
||||
int x;
|
||||
int c;
|
||||
@@ -217,10 +217,10 @@ ogc_poll(void *priv)
|
||||
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;
|
||||
@@ -231,7 +231,7 @@ ogc_poll(void *priv)
|
||||
ogc->cga.cgastat |= 1;
|
||||
ogc->cga.linepos = 1;
|
||||
oldsc = ogc->cga.sc;
|
||||
if ((ogc->cga.crtc[8] & 3) == 3)
|
||||
if ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3)
|
||||
ogc->cga.sc = ((ogc->cga.sc << 1) + ogc->cga.oddeven) & 7;
|
||||
if (ogc->cga.cgadispon) {
|
||||
if (ogc->cga.displine < ogc->cga.firstline) {
|
||||
@@ -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.ma == ca) && 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) {
|
||||
@@ -293,15 +293,15 @@ ogc_poll(void *priv)
|
||||
}
|
||||
}
|
||||
/* 40-col */
|
||||
else if (!(ogc->cga.cgamode & 2)) {
|
||||
for (x = 0; x < ogc->cga.crtc[1]; x++) {
|
||||
if (ogc->cga.cgamode & 8) {
|
||||
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.ma << 1) & 0x3fff) + ogc->base];
|
||||
attr = ogc->cga.vram[(((ogc->cga.ma << 1) + 1) & 0x3fff) + ogc->base];
|
||||
} else {
|
||||
chr = attr = 0;
|
||||
}
|
||||
drawcursor = ((ogc->cga.ma == ca) && ogc->cga.con && ogc->cga.cursoron);
|
||||
drawcursor = ((ogc->cga.ma == ca) && 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 */
|
||||
@@ -352,9 +352,9 @@ ogc_poll(void *priv)
|
||||
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) {
|
||||
if (ogc->cga.cgamode & CGA_MODE_FLAG_VIDEO_ENABLE) {
|
||||
dat = (ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2] << 8) | ogc->cga.vram[((ogc->cga.ma << 1) & 0x1fff) + dat2 + 1];
|
||||
} else {
|
||||
dat = 0;
|
||||
@@ -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)
|
||||
if (ogc->cga.vc == ogc->cga.crtc[CGA_CRTC_VSYNC] && !ogc->cga.sc)
|
||||
ogc->cga.cgastat |= 8;
|
||||
ogc->cga.displine++;
|
||||
if (ogc->cga.displine >= 720)
|
||||
@@ -405,10 +405,10 @@ ogc_poll(void *priv)
|
||||
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;
|
||||
if (ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_CURSOR_END] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == ((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))
|
||||
if ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))
|
||||
ogc->cga.maback = ogc->cga.ma;
|
||||
if (ogc->cga.vadj) {
|
||||
ogc->cga.sc++;
|
||||
@@ -417,28 +417,28 @@ ogc_poll(void *priv)
|
||||
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.ma = ogc->cga.maback = (ogc->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (ogc->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
|
||||
ogc->cga.sc = 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))) {
|
||||
// may cause problems with composite
|
||||
} else if (ogc->cga.sc == ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == (ogc->cga.crtc[CGA_CRTC_MAX_SCANLINE_ADDR] >> 1))) {
|
||||
ogc->cga.maback = ogc->cga.ma;
|
||||
ogc->cga.sc = 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.ma = ogc->cga.maback = (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;
|
||||
@@ -450,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;
|
||||
@@ -474,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));
|
||||
@@ -496,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;
|
||||
@@ -524,12 +524,12 @@ ogc_poll(void *priv)
|
||||
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.sc == (ogc->cga.crtc[CGA_CRTC_CURSOR_START] & 31) || ((ogc->cga.crtc[CGA_CRTC_INTERLACE] & 3) == 3 && ogc->cga.sc == ((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++)
|
||||
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.ma << 1) + x) & 0x3fff) + ogc->base];
|
||||
}
|
||||
}
|
||||
@@ -246,24 +246,24 @@ t1000_text_row80(t1000_t *t1000)
|
||||
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;
|
||||
uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
|
||||
uint16_t ca = (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;
|
||||
|
||||
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) <= sc) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= sc);
|
||||
}
|
||||
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 = ((ma == ca) && 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];
|
||||
@@ -307,24 +307,24 @@ t1000_text_row40(t1000_t *t1000)
|
||||
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;
|
||||
uint16_t ma = (t1000->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t1000->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x3fff;
|
||||
uint16_t ca = (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;
|
||||
|
||||
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) <= sc) && ((t1000->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= sc);
|
||||
}
|
||||
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 = ((ma == ca) && 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];
|
||||
@@ -366,7 +366,7 @@ 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 ma = (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);
|
||||
|
||||
@@ -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,7 +395,7 @@ t1000_cgaline4(t1000_t *t1000)
|
||||
uint32_t ink1;
|
||||
uint16_t addr;
|
||||
|
||||
uint16_t ma = (t1000->cga.crtc[13] | (t1000->cga.crtc[12] << 8)) & 0x3fff;
|
||||
uint16_t ma = (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);
|
||||
|
||||
for (uint8_t x = 0; x < 80; x++) {
|
||||
@@ -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;
|
||||
@@ -255,24 +255,24 @@ t3100e_text_row80(t3100e_t *t3100e)
|
||||
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;
|
||||
uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
|
||||
uint16_t ca = (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;
|
||||
|
||||
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 <= sc) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= sc);
|
||||
}
|
||||
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 = ((ma == ca) && 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];
|
||||
@@ -316,24 +316,24 @@ t3100e_text_row40(t3100e_t *t3100e)
|
||||
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;
|
||||
uint16_t ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 8)) & 0x7fff;
|
||||
uint16_t ca = (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;
|
||||
|
||||
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 <= sc) && ((t3100e->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) * 2 >= sc);
|
||||
}
|
||||
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 = ((ma == ca) && 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];
|
||||
@@ -374,9 +374,9 @@ 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 ma = (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);
|
||||
} else {
|
||||
@@ -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,8 +407,8 @@ 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 ma = (t3100e->cga.crtc[CGA_CRTC_START_ADDR_HIGH] | (t3100e->cga.crtc[CGA_CRTC_CURSOR_END] << 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);
|
||||
} else /* 320*200 */
|
||||
@@ -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) {
|
||||
@@ -498,7 +498,7 @@ t3100e_poll(void *priv)
|
||||
|
||||
/* Graphics */
|
||||
if (t3100e->cga.cgamode & 0x02) {
|
||||
if (t3100e->cga.cgamode & 0x10)
|
||||
if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)
|
||||
t3100e_cgaline6(t3100e);
|
||||
else
|
||||
t3100e_cgaline4(t3100e);
|
||||
@@ -551,7 +551,7 @@ t3100e_poll(void *priv)
|
||||
video_res_y = T3100E_YSIZE;
|
||||
|
||||
if (t3100e->cga.cgamode & 0x02) {
|
||||
if (t3100e->cga.cgamode & 0x10)
|
||||
if (t3100e->cga.cgamode & CGA_MODE_FLAG_HIGHRES_GRAPHICS)
|
||||
video_bpp = 1;
|
||||
else
|
||||
video_bpp = 2;
|
||||
@@ -901,7 +901,7 @@ ega_poll(void *priv)
|
||||
|
||||
ega->linepos = 0;
|
||||
if ((ega->sc == (ega->crtc[11] & 31)) || (ega->sc == ega->rowcount))
|
||||
ega->con = 0;
|
||||
ega->cursorvisible = 0;
|
||||
if (ega->dispon) {
|
||||
/* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll */
|
||||
if (ega->linedbl && !ega->linecountff) {
|
||||
@@ -1037,7 +1037,7 @@ ega_poll(void *priv)
|
||||
ega->linecountff = 0;
|
||||
}
|
||||
if (ega->sc == (ega->crtc[10] & 31))
|
||||
ega->con = 1;
|
||||
ega->cursorvisible = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ 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;
|
||||
|
||||
int drawcursor = ((ega->ma == ega->ca) && ega->con && ega->cursoron);
|
||||
int drawcursor = ((ega->ma == ega->ca) && ega->cursorvisible && ega->cursoron);
|
||||
|
||||
uint32_t chr;
|
||||
uint32_t attr;
|
||||
|
||||
@@ -362,27 +362,27 @@ f82c425_text_row(f82c425_t *f82c425)
|
||||
int blink;
|
||||
uint16_t addr;
|
||||
uint8_t sc;
|
||||
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
|
||||
uint16_t ma = (f82c425->cga.crtc[CGA_CRTC_START_ADDR_LOW] | (f82c425->cga.crtc[CGA_CRTC_START_ADDR_HIGH] << 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 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;
|
||||
|
||||
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) <= sc) && ((f82c425->cga.crtc[CGA_CRTC_CURSOR_END] & 0x0F) >= sc);
|
||||
}
|
||||
|
||||
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 = ((ma == ca) && 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];
|
||||
@@ -418,7 +418,7 @@ 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 ma = (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);
|
||||
|
||||
@@ -442,7 +442,7 @@ f82c425_cgaline4(f82c425_t *f82c425)
|
||||
uint8_t pattern;
|
||||
uint16_t addr;
|
||||
|
||||
uint16_t ma = (f82c425->cga.crtc[0x0d] | (f82c425->cga.crtc[0x0c] << 8)) & 0x3fff;
|
||||
uint16_t ma = (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);
|
||||
|
||||
for (uint8_t x = 0; x < 80; x++) {
|
||||
@@ -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;
|
||||
|
||||
@@ -341,7 +341,7 @@ hercules_poll(void *priv)
|
||||
attr = dev->charbuffer[(x << 1) + 1];
|
||||
} else
|
||||
chr = attr = 0;
|
||||
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
|
||||
drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron);
|
||||
blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor);
|
||||
|
||||
if (dev->sc == 12 && ((attr & 7) == 1)) {
|
||||
@@ -398,7 +398,7 @@ hercules_poll(void *priv)
|
||||
}
|
||||
|
||||
if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
|
||||
dev->con = 0;
|
||||
dev->cursorvisible = 0;
|
||||
}
|
||||
|
||||
if (dev->vadj) {
|
||||
@@ -517,7 +517,7 @@ hercules_poll(void *priv)
|
||||
}
|
||||
|
||||
if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))
|
||||
dev->con = 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;
|
||||
|
||||
@@ -167,7 +167,7 @@ typedef struct {
|
||||
int linepos, displine;
|
||||
int vc, sc;
|
||||
uint16_t ma, maback;
|
||||
int con, cursoron;
|
||||
int cursorvisible, cursoron;
|
||||
int dispon, blink;
|
||||
int vsynctime;
|
||||
int vadj;
|
||||
@@ -760,7 +760,7 @@ text_line(incolor_t *dev, uint16_t ca)
|
||||
} else
|
||||
chr = attr = 0;
|
||||
|
||||
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
|
||||
drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron);
|
||||
|
||||
switch (dev->crtc[INCOLOR_CRTC_XMODE] & 5) {
|
||||
case 0:
|
||||
@@ -898,7 +898,7 @@ incolor_poll(void *priv)
|
||||
}
|
||||
|
||||
if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
|
||||
dev->con = 0;
|
||||
dev->cursorvisible = 0;
|
||||
}
|
||||
|
||||
if (dev->vadj) {
|
||||
@@ -977,7 +977,7 @@ incolor_poll(void *priv)
|
||||
}
|
||||
|
||||
if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))
|
||||
dev->con = 1;
|
||||
dev->cursorvisible = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ typedef struct {
|
||||
int linepos, displine;
|
||||
int vc, sc;
|
||||
uint16_t ma, maback;
|
||||
int con, cursoron;
|
||||
int cursorvisible, cursoron;
|
||||
int dispon, blink;
|
||||
int vsynctime;
|
||||
int vadj;
|
||||
@@ -418,7 +418,7 @@ text_line(herculesplus_t *dev, uint16_t ca)
|
||||
} else
|
||||
chr = attr = 0;
|
||||
|
||||
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
|
||||
drawcursor = ((dev->ma == ca) && dev->cursorvisible && dev->cursoron);
|
||||
|
||||
switch (dev->crtc[HERCULESPLUS_CRTC_XMODE] & 5) {
|
||||
case 0:
|
||||
@@ -535,7 +535,7 @@ herculesplus_poll(void *priv)
|
||||
}
|
||||
|
||||
if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
|
||||
dev->con = 0;
|
||||
dev->cursorvisible = 0;
|
||||
}
|
||||
if (dev->vadj) {
|
||||
dev->sc++;
|
||||
@@ -612,7 +612,7 @@ herculesplus_poll(void *priv)
|
||||
}
|
||||
|
||||
if (dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))
|
||||
dev->con = 1;
|
||||
dev->cursorvisible = 1;
|
||||
}
|
||||
|
||||
VIDEO_MONITOR_EPILOGUE();
|
||||
@@ -113,7 +113,7 @@ 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;
|
||||
|
||||
@@ -158,7 +158,7 @@ mda_poll(void *priv)
|
||||
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);
|
||||
drawcursor = ((mda->ma == ca) && mda->cursorvisible && 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++)
|
||||
@@ -199,7 +199,7 @@ mda_poll(void *priv)
|
||||
}
|
||||
}
|
||||
if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) {
|
||||
mda->con = 0;
|
||||
mda->cursorvisible = 0;
|
||||
}
|
||||
if (mda->vadj) {
|
||||
mda->sc++;
|
||||
@@ -266,7 +266,7 @@ mda_poll(void *priv)
|
||||
mda->ma = mda->maback;
|
||||
}
|
||||
if (mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1))) {
|
||||
mda->con = 1;
|
||||
mda->cursorvisible = 1;
|
||||
}
|
||||
}
|
||||
VIDEO_MONITOR_EPILOGUE();
|
||||
|
||||
703
src/video/vid_pcjr.c
Normal file
703
src/video/vid_pcjr.c
Normal 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->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->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->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->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->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->cursorvisible = 0;
|
||||
}
|
||||
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->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();
|
||||
}
|
||||
@@ -362,7 +362,7 @@ typedef struct da2_t {
|
||||
int vc;
|
||||
int sc;
|
||||
int linepos, vslines, linecountff;
|
||||
int con, cursoron, blink, blinkconf;
|
||||
int cursorvisible, cursoron, blink, blinkconf;
|
||||
int scrollcache;
|
||||
int char_width;
|
||||
|
||||
@@ -2055,7 +2055,7 @@ da2_render_text(da2_t *da2)
|
||||
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);
|
||||
drawcursor = ((da2->ma == da2->ca) && da2->cursorvisible && da2->cursoron);
|
||||
if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= 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 */
|
||||
@@ -2155,7 +2155,7 @@ da2_render_textm3(da2_t *da2)
|
||||
}
|
||||
chr_wide = 0;
|
||||
}
|
||||
drawcursor = ((da2->ma == da2->ca) && da2->con && da2->cursoron);
|
||||
drawcursor = ((da2->ma == da2->ca) && da2->cursorvisible && da2->cursoron);
|
||||
if (drawcursor && da2->sc >= da2->crtc[LC_CURSOR_ROW_START] && da2->sc <= 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 */
|
||||
@@ -3056,7 +3056,7 @@ da2_poll(void *priv)
|
||||
|
||||
da2->linepos = 0;
|
||||
if (da2->sc == (da2->crtc[LC_CURSOR_ROW_END] & 31))
|
||||
da2->con = 0;
|
||||
da2->cursorvisible = 0;
|
||||
if (da2->dispon) {
|
||||
if (da2->sc == da2->rowcount) {
|
||||
da2->linecountff = 0;
|
||||
@@ -3145,7 +3145,7 @@ da2_poll(void *priv)
|
||||
da2->scrollcache = da2->attrc[LV_PANNING] & 7;
|
||||
}
|
||||
if (da2->sc == (da2->crtc[LC_CURSOR_ROW_START] & 31))
|
||||
da2->con = 1;
|
||||
da2->cursorvisible = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ typedef struct sigma_t {
|
||||
int linepos, displine;
|
||||
int sc, vc;
|
||||
int cgadispon;
|
||||
int con, cursoron, cgablink;
|
||||
int cursorvisible, cursoron, cgablink;
|
||||
int vsynctime, vadj;
|
||||
int oddeven;
|
||||
|
||||
@@ -430,7 +430,7 @@ sigma_text80(sigma_t *sigma)
|
||||
for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) {
|
||||
chr = vram[x << 1];
|
||||
attr = vram[(x << 1) + 1];
|
||||
drawcursor = ((ma == ca) && sigma->con && sigma->cursoron);
|
||||
drawcursor = ((ma == ca) && sigma->cursorvisible && sigma->cursoron);
|
||||
|
||||
if (!(sigma->sigmamode & MODE_NOBLINK)) {
|
||||
cols[1] = (attr & 15) | 16;
|
||||
@@ -485,7 +485,7 @@ sigma_text40(sigma_t *sigma)
|
||||
for (uint32_t x = 0; x < (sigma->crtc[1] << 1); x++) {
|
||||
chr = vram[x << 1];
|
||||
attr = vram[(x << 1) + 1];
|
||||
drawcursor = ((ma == ca) && sigma->con && sigma->cursoron);
|
||||
drawcursor = ((ma == ca) && sigma->cursorvisible && sigma->cursoron);
|
||||
|
||||
if (!(sigma->sigmamode & MODE_NOBLINK)) {
|
||||
cols[1] = (attr & 15) | 16;
|
||||
@@ -675,7 +675,7 @@ sigma_poll(void *priv)
|
||||
sigma->sigmastat &= ~STATUS_RETR_V;
|
||||
}
|
||||
if (sigma->sc == (sigma->crtc[11] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[11] & 31) >> 1))) {
|
||||
sigma->con = 0;
|
||||
sigma->cursorvisible = 0;
|
||||
}
|
||||
if ((sigma->crtc[8] & 3) == 3 && sigma->sc == (sigma->crtc[9] >> 1))
|
||||
sigma->maback = sigma->ma;
|
||||
@@ -775,7 +775,7 @@ sigma_poll(void *priv)
|
||||
if (sigma->cgadispon)
|
||||
sigma->sigmastat &= ~STATUS_RETR_H;
|
||||
if (sigma->sc == (sigma->crtc[10] & 31) || ((sigma->crtc[8] & 3) == 3 && sigma->sc == ((sigma->crtc[10] & 31) >> 1)))
|
||||
sigma->con = 1;
|
||||
sigma->cursorvisible = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1332,7 +1332,7 @@ svga_poll(void *priv)
|
||||
|
||||
svga->linepos = 0;
|
||||
if ((svga->sc == (svga->crtc[11] & 31)) || (svga->sc == svga->rowcount))
|
||||
svga->con = 0;
|
||||
svga->cursorvisible = 0;
|
||||
if (svga->dispon) {
|
||||
/* TODO: Verify real hardware behaviour for out-of-range fine vertical scroll
|
||||
- S3 Trio64V2/DX: sc == rowcount, wrapping 5-bit counter. */
|
||||
@@ -1503,7 +1503,7 @@ svga_poll(void *priv)
|
||||
svga->overlay_latch = svga->overlay;
|
||||
}
|
||||
if (svga->sc == (svga->crtc[10] & 31))
|
||||
svga->con = 1;
|
||||
svga->cursorvisible = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ svga_render_text_40(svga_t *svga)
|
||||
if (!svga->force_old_addr)
|
||||
addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask;
|
||||
|
||||
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
|
||||
drawcursor = ((svga->ma == svga->ca) && svga->cursorvisible && svga->cursoron);
|
||||
|
||||
if (svga->force_old_addr) {
|
||||
chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
|
||||
@@ -241,7 +241,7 @@ svga_render_text_80(svga_t *svga)
|
||||
if (!svga->force_old_addr)
|
||||
addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask;
|
||||
|
||||
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
|
||||
drawcursor = ((svga->ma == svga->ca) && svga->cursorvisible && svga->cursoron);
|
||||
|
||||
if (svga->force_old_addr) {
|
||||
chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
|
||||
@@ -318,7 +318,7 @@ svga_render_text_80_ksc5601(svga_t *svga)
|
||||
|
||||
for (int x = 0; x < (svga->hdisp + svga->scrollcache); x += xinc) {
|
||||
uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask;
|
||||
drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
|
||||
drawcursor = ((svga->ma == svga->ca) && svga->cursorvisible && svga->cursoron);
|
||||
chr = svga->vram[addr];
|
||||
nextchr = svga->vram[addr + 8];
|
||||
attr = svga->vram[addr + 1];
|
||||
|
||||
827
src/video/vid_tandy.c
Normal file
827
src/video/vid_tandy.c
Normal file
@@ -0,0 +1,827 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Tandy 1000 video 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 2025 starfrost
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/sound.h>
|
||||
#include <86box/snd_sn76489.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_cga_comp.h>
|
||||
#include <86box/m_tandy.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
enum {
|
||||
TANDY_RGB = 0,
|
||||
TANDY_COMPOSITE
|
||||
};
|
||||
|
||||
static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/
|
||||
|
||||
static void
|
||||
recalc_mapping(tandy_t *dev)
|
||||
{
|
||||
t1kvid_t *vid = dev->vid;
|
||||
|
||||
mem_mapping_disable(&vid->mapping);
|
||||
io_removehandler(0x03d0, 16,
|
||||
tandy_vid_in, NULL, NULL, tandy_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, tandy_vid_in, NULL, NULL, tandy_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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tandy_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;
|
||||
}
|
||||
|
||||
void
|
||||
tandy_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);
|
||||
tandy_recalc_address_sl(dev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03df:
|
||||
vid->memctrl = val;
|
||||
if (dev->is_sl2)
|
||||
tandy_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;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
tandy_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->cursorvisible && 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->cursorvisible && 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->cursorvisible = 0;
|
||||
}
|
||||
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->cursorvisible = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tandy_vid_speed_changed(void *priv)
|
||||
{
|
||||
tandy_t *dev = (tandy_t *) priv;
|
||||
|
||||
recalc_timings(dev);
|
||||
}
|
||||
|
||||
void
|
||||
tandy_vid_close(void *priv)
|
||||
{
|
||||
tandy_t *dev = (tandy_t *) priv;
|
||||
|
||||
free(dev->vid);
|
||||
dev->vid = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
tandy_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, tandy_vid_in, NULL, NULL, tandy_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,
|
||||
tandy_vid_in, NULL, NULL, tandy_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 tandy_1000_video_device = {
|
||||
.name = "Tandy 1000",
|
||||
.internal_name = "tandy1000_video",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = NULL,
|
||||
.close = tandy_vid_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = tandy_vid_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = vid_config
|
||||
};
|
||||
|
||||
const device_t tandy_1000hx_video_device = {
|
||||
.name = "Tandy 1000 HX",
|
||||
.internal_name = "tandy1000_hx_video",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = NULL,
|
||||
.close = tandy_vid_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = tandy_vid_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = vid_config
|
||||
};
|
||||
|
||||
const device_t tandy_1000sl_video_device = {
|
||||
.name = "Tandy 1000SL2",
|
||||
.internal_name = "tandy1000_sl_video",
|
||||
.flags = 0,
|
||||
.local = 1,
|
||||
.init = NULL,
|
||||
.close = tandy_vid_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = tandy_vid_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
Reference in New Issue
Block a user