Re-worked the ST506 driver for XT, adding support for Seagate ST-11 and WD-1002 controllers, and RLL mode.
Added John Elliott's implementation of the IBM PGC controller, and the ImageManager 1024 clone card. The PGC is not working properly yet, pending conversion to our video backend.
This commit is contained in:
@@ -8,12 +8,12 @@
|
||||
*
|
||||
* Common code to handle all sorts of disk controllers.
|
||||
*
|
||||
* Version: @(#)hdc.c 1.0.16 2018/10/20
|
||||
* Version: @(#)hdc.c 1.0.17 2019/02/24
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -63,6 +63,10 @@ static const struct {
|
||||
|
||||
{ "st506_xt", &st506_xt_xebec_device },
|
||||
{ "st506_dtc5150x", &st506_xt_dtc5150x_device },
|
||||
{ "st506_st11_m", &st506_xt_st11_m_device },
|
||||
{ "st506_st11_r", &st506_xt_st11_r_device },
|
||||
{ "st506_wd1002a_wx1", &st506_xt_wd1002a_wx1_device },
|
||||
{ "st506_wd1002a_27x", &st506_xt_wd1002a_27x_device },
|
||||
|
||||
{ "xta_wdxt150", &xta_wdxt150_device },
|
||||
|
||||
@@ -97,7 +101,7 @@ hdc_log(int level, const char *fmt, ...)
|
||||
# ifdef ENABLE_HDC_LOG
|
||||
va_list ap;
|
||||
|
||||
if (hdc_do_log >= level) {
|
||||
if ((hdc_do_log + LOG_INFO) >= level) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
*
|
||||
* Definitions for the common disk controller handler.
|
||||
*
|
||||
* Version: @(#)hdc.h 1.0.14 2018/09/28
|
||||
* Version: @(#)hdc.h 1.0.15 2019/02/24
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -57,6 +57,10 @@ extern "C" {
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t st506_xt_xebec_device; /* st506_xt_xebec */
|
||||
extern const device_t st506_xt_dtc5150x_device; /* st506_xt_dtc */
|
||||
extern const device_t st506_xt_st11_m_device; /* st506_xt_st11_m */
|
||||
extern const device_t st506_xt_st11_r_device; /* st506_xt_st11_r */
|
||||
extern const device_t st506_xt_wd1002a_wx1_device; /* st506_xt_wd1002a_wx1 */
|
||||
extern const device_t st506_xt_wd1002a_27x_device; /* st506_xt_wd1002a_27x */
|
||||
|
||||
extern const device_t st506_at_wd1003_device; /* st506_at_wd1003 */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -427,7 +427,6 @@ dma_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
|
||||
dma_m |= (1 << (val & 3));
|
||||
else
|
||||
dma_m &= ~(1 << (val & 3));
|
||||
if ((val & 3) == 3) INFO("DMA: mask=%02x\n", dma_m);
|
||||
return;
|
||||
|
||||
case 0xb: /*Mode*/
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* Emulation of the old and new IBM CGA graphics cards.
|
||||
*
|
||||
* Version: @(#)vid_cga.c 1.0.10 2019/02/12
|
||||
* Version: @(#)vid_cga.c 1.0.11 2019/01/01
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -55,8 +55,6 @@
|
||||
#include "vid_cga_comp.h"
|
||||
|
||||
|
||||
#define CGA_FONT_ROM_PATH L"video/ibm/cga/cga.rom"
|
||||
|
||||
#define CGA_RGB 0
|
||||
#define CGA_COMPOSITE 1
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
*
|
||||
* Definitions for the CGA driver.
|
||||
*
|
||||
* Version: @(#)vid_cga.h 1.0.5 2018/10/05
|
||||
* Version: @(#)vid_cga.h 1.0.6 2019/03/01
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||
*
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
*
|
||||
@@ -40,6 +40,9 @@
|
||||
# define VIDEO_CGA_H
|
||||
|
||||
|
||||
#define CGA_FONT_ROM_PATH L"video/ibm/cga/cga.rom"
|
||||
|
||||
|
||||
typedef struct {
|
||||
mem_map_t mapping;
|
||||
|
||||
|
||||
913
src/devices/video/vid_im1024.c
Normal file
913
src/devices/video/vid_im1024.c
Normal file
@@ -0,0 +1,913 @@
|
||||
/*
|
||||
* VARCem Virtual ARchaeological Computer EMulator.
|
||||
* An emulator of (mostly) x86-based PC systems and devices,
|
||||
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
||||
* spanning the era between 1981 and 1995.
|
||||
*
|
||||
* This file is part of the VARCem Project.
|
||||
*
|
||||
* Emulation of the ImageManager 1024 video controller.
|
||||
*
|
||||
* Just enough of the Vermont Microsystems IM-1024 is implemented
|
||||
* to support the Windows 1.03 driver. Functions are partially
|
||||
* implemented or hardwired to the behavior expected by the
|
||||
* Windows driver.
|
||||
*
|
||||
* One major difference seems to be that in hex mode, coordinates
|
||||
* are passed as 2-byte integer words rather than 4-byte
|
||||
* fixed-point fractions.
|
||||
*
|
||||
* It is unknown what triggers this, so for now it's always on.
|
||||
*
|
||||
* As well as the usual PGC ring buffer at 0xC6000, the IM1024
|
||||
* appears to have an alternate method of passing commands. This
|
||||
* is enabled by setting 0xC6330 to 1, and then:
|
||||
*
|
||||
* CX = count to write
|
||||
* SI -> bytes to write
|
||||
*
|
||||
* Set pending bytes to 0
|
||||
* Read [C6331]. This gives number of bytes that can be written:
|
||||
* 0xFF => 0, 0xFE => 1, 0xFD => 2 etc.
|
||||
* Write that number of bytes to C6000.
|
||||
* If there are more to come, go back to reading [C6331].
|
||||
*
|
||||
* As far as can be determined, at least one byte is always
|
||||
* written; there is no provision to pause if the queue is full.
|
||||
*
|
||||
* This is implemented by holding a FIFO of unlimited depth in
|
||||
* the IM1024 to receive the data.
|
||||
*
|
||||
* Version: @(#)vid_im1024.c 1.0.1 2019/03/01
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* John Elliott, <jce@seasip.info>
|
||||
*
|
||||
* Copyright 2019 Fred N. van Kempen.
|
||||
* Copyright 2019 John Elliott.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the:
|
||||
*
|
||||
* Free Software Foundation, Inc.
|
||||
* 59 Temple Place - Suite 330
|
||||
* Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <ctype.h>
|
||||
#include "../../emu.h"
|
||||
#include "../../io.h"
|
||||
#include "../../mem.h"
|
||||
#include "../../rom.h"
|
||||
#include "../../timer.h"
|
||||
#include "../../device.h"
|
||||
#include "../system/pit.h"
|
||||
#include "../../plat.h"
|
||||
#include "video.h"
|
||||
#include "vid_pgc.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
pgc_t pgc;
|
||||
|
||||
uint8_t fontx[256];
|
||||
uint8_t fonty[256];
|
||||
uint8_t font[256][128];
|
||||
|
||||
uint8_t *fifo;
|
||||
unsigned fifo_len,
|
||||
fifo_wrptr,
|
||||
fifo_rdptr;
|
||||
} im1024_t;
|
||||
|
||||
|
||||
static void
|
||||
fifo_write(im1024_t *dev, uint8_t val)
|
||||
{
|
||||
#if 0
|
||||
DEBUG(("fifo_write: %02x [rd=%04x wr=%04x]\n",
|
||||
val, dev->fifo_rdptr, dev->fifo_wrptr));
|
||||
#endif
|
||||
|
||||
if (((dev->fifo_wrptr + 1) % dev->fifo_len) == dev->fifo_rdptr) {
|
||||
/* FIFO is full. Double its size. */
|
||||
uint8_t *buf;
|
||||
|
||||
DEBUG("fifo_resize: %d to %d\n", dev->fifo_len, 2 * dev->fifo_len);
|
||||
|
||||
buf = realloc(dev->fifo, 2 * dev->fifo_len);
|
||||
if (buf == NULL) return;
|
||||
|
||||
/* Move the [0..wrptr] range to the newly-allocated area [len..len+wrptr] */
|
||||
memmove(buf + dev->fifo_len, buf, dev->fifo_wrptr);
|
||||
dev->fifo = buf;
|
||||
dev->fifo_wrptr += dev->fifo_len;
|
||||
dev->fifo_len *= 2;
|
||||
}
|
||||
|
||||
/* Append to the queue */
|
||||
dev->fifo[dev->fifo_wrptr++] = val;
|
||||
|
||||
/* Wrap if end of buffer reached */
|
||||
if (dev->fifo_wrptr >= dev->fifo_len)
|
||||
dev->fifo_wrptr = 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fifo_read(im1024_t *dev)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
if (dev->fifo_wrptr == dev->fifo_rdptr)
|
||||
return -1; /* FIFO empty */
|
||||
|
||||
ret = dev->fifo[dev->fifo_rdptr++];
|
||||
if (dev->fifo_rdptr >= dev->fifo_len)
|
||||
dev->fifo_rdptr = 0;
|
||||
|
||||
DBGLOG(1, "fifo_read: %02x\n", ret);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Where a normal PGC would just read from the ring buffer at 0xC6300, the
|
||||
* IM-1024 can read either from this or from its internal FIFO. The internal
|
||||
* FIFO has priority. */
|
||||
static int
|
||||
input_byte(pgc_t *pgc, uint8_t *result)
|
||||
{
|
||||
im1024_t *dev = (im1024_t *)pgc;
|
||||
|
||||
/* If input buffer empty, wait for it to fill */
|
||||
while ((dev->fifo_wrptr == dev->fifo_rdptr) &&
|
||||
(pgc->mapram[0x300] == pgc->mapram[0x301])) {
|
||||
pgc->waiting_input_fifo = 1;
|
||||
pgc_sleep(pgc);
|
||||
}
|
||||
|
||||
if (pgc->mapram[0x3ff]) { /* Reset triggered */
|
||||
pgc_reset(pgc);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (dev->fifo_wrptr == dev->fifo_rdptr) {
|
||||
*result = pgc->mapram[pgc->mapram[0x301]];
|
||||
++pgc->mapram[0x301];
|
||||
} else {
|
||||
*result = fifo_read(dev);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Macros to disable clipping and save clip state */
|
||||
#define PUSHCLIP { \
|
||||
uint16_t vp_x1, vp_x2, vp_y1, vp_y2; \
|
||||
vp_x1 = pgc->vp_x1; \
|
||||
vp_y1 = pgc->vp_y1; \
|
||||
vp_x2 = pgc->vp_x2; \
|
||||
vp_y2 = pgc->vp_y2; \
|
||||
pgc->vp_x1 = 0; \
|
||||
pgc->vp_y1 = 0; \
|
||||
pgc->vp_x2 = pgc->maxw - 1; \
|
||||
pgc->vp_y2 = pgc->maxh - 1; \
|
||||
|
||||
/* And to restore clip state */
|
||||
#define POPCLIP \
|
||||
pgc->vp_x1 = vp_x1; \
|
||||
pgc->vp_y1 = vp_y1; \
|
||||
pgc->vp_x2 = vp_x2; \
|
||||
pgc->vp_y2 = vp_y2; \
|
||||
}
|
||||
|
||||
|
||||
/* Override memory read to return FIFO space. */
|
||||
static uint8_t
|
||||
im1024_read(uint32_t addr, void *priv)
|
||||
{
|
||||
im1024_t *dev = (im1024_t *)priv;
|
||||
|
||||
if (addr == 0xC6331 && dev->pgc.mapram[0x330] == 1) {
|
||||
/* Hardcode that there are 128 bytes free. */
|
||||
return(0x80);
|
||||
}
|
||||
|
||||
return(pgc_read(addr, &dev->pgc));
|
||||
}
|
||||
|
||||
|
||||
/* Override memory write to handle writes to the FIFO. */
|
||||
static void
|
||||
im1024_write(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
im1024_t *dev = (im1024_t *)priv;
|
||||
|
||||
/* If we are in 'fast' input mode, send all writes to the internal
|
||||
* FIFO */
|
||||
if (addr >= 0xC6000 && addr < 0xC6100 && dev->pgc.mapram[0x330] == 1) {
|
||||
fifo_write(dev, val);
|
||||
|
||||
DBGLOG(1, "im1024_write(%02x)\n", val);
|
||||
|
||||
if (dev->pgc.waiting_input_fifo) {
|
||||
dev->pgc.waiting_input_fifo = 0;
|
||||
pgc_wake(&dev->pgc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
pgc_write(addr, val, &dev->pgc);
|
||||
}
|
||||
|
||||
|
||||
/* I don't know what the IMGSIZ command does, only that the Windows driver
|
||||
* issues it. So just parse and ignore it */
|
||||
static void
|
||||
hndl_imgsiz(pgc_t *pgc)
|
||||
{
|
||||
#if 0
|
||||
im1024_t *dev = (im1024_t *)pgc;
|
||||
#endif
|
||||
int16_t w, h;
|
||||
uint8_t a, b;
|
||||
|
||||
if (! pgc_param_word(pgc, &w)) return;
|
||||
if (! pgc_param_word(pgc, &h)) return;
|
||||
if (! pgc_param_byte(pgc, &a)) return;
|
||||
if (! pgc_param_byte(pgc, &b)) return;
|
||||
|
||||
DEBUG("IMGSIZ %d,%d,%d,%d\n", w, h, a, b);
|
||||
}
|
||||
|
||||
|
||||
/* I don't know what the IPREC command does, only that the Windows driver
|
||||
* issues it. So just parse and ignore it */
|
||||
static void
|
||||
hndl_iprec(pgc_t *pgc)
|
||||
{
|
||||
#if 0
|
||||
im1024_t *dev = (im1024_t *)pgc;
|
||||
#endif
|
||||
uint8_t param;
|
||||
|
||||
if (! pgc_param_byte(pgc, ¶m)) return;
|
||||
|
||||
DEBUG("IPREC %d\n", param);
|
||||
}
|
||||
|
||||
|
||||
/* I think PAN controls which part of the 1024x1024 framebuffer is displayed
|
||||
* in the 1024x800 visible screen. */
|
||||
static void
|
||||
hndl_pan(pgc_t *pgc)
|
||||
{
|
||||
int16_t x, y;
|
||||
|
||||
if (! pgc_param_word(pgc, &x)) return;
|
||||
if (! pgc_param_word(pgc, &y)) return;
|
||||
|
||||
DEBUG("PAN %d,%d\n", x, y);
|
||||
|
||||
pgc->pan_x = x;
|
||||
pgc->pan_y = y;
|
||||
}
|
||||
|
||||
|
||||
/* PLINE draws a non-filled polyline at a fixed position */
|
||||
static void
|
||||
hndl_pline(pgc_t *pgc)
|
||||
{
|
||||
int16_t x[257], y[257];
|
||||
uint16_t linemask = pgc->line_pattern;
|
||||
uint8_t count;
|
||||
unsigned n;
|
||||
|
||||
if (! pgc_param_byte(pgc, &count)) return;
|
||||
|
||||
DEBUG("PLINE<IM1024> (%d) ", count);
|
||||
for (n = 0; n < count; n++) {
|
||||
if (! pgc_param_word(pgc, &x[n])) return;
|
||||
if (! pgc_param_word(pgc, &y[n])) return;
|
||||
DEBUG(" (%d,%d)\n", x[n], y[n]);
|
||||
}
|
||||
|
||||
for (n = 1; n < count; n++) {
|
||||
linemask = pgc_draw_line(pgc, x[n - 1] << 16, y[n - 1] << 16,
|
||||
x[n] << 16, y[n] << 16, linemask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Blit a single row of pixels from one location to another. To avoid
|
||||
* difficulties if the two overlap, read both rows into memory, process them
|
||||
* there, and write the result back. */
|
||||
static void
|
||||
blkmov_row(pgc_t *pgc, int16_t x0, int16_t x1, int16_t x2, int16_t sy, int16_t ty)
|
||||
{
|
||||
uint8_t src[1024];
|
||||
uint8_t dst[1024];
|
||||
int16_t x;
|
||||
|
||||
for (x = x0; x <= x1; x++) {
|
||||
src[x - x0] = pgc_read_pixel(pgc, x, sy);
|
||||
dst[x - x0] = pgc_read_pixel(pgc, x - x0 + x2, ty);
|
||||
}
|
||||
|
||||
for (x = x0; x <= x1; x++) {
|
||||
switch (pgc->draw_mode) {
|
||||
default:
|
||||
case 0:
|
||||
pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
pgc_write_pixel(pgc, (x - x0 + x2), ty, dst[x - x0] ^ 0xFF);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] ^ dst[x - x0]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
pgc_write_pixel(pgc, (x - x0 + x2), ty, src[x - x0] & dst[x - x0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* BLKMOV blits a rectangular area from one location to another, with no
|
||||
* clipping. */
|
||||
static void
|
||||
hndl_blkmov(pgc_t *pgc)
|
||||
{
|
||||
#if 0
|
||||
im1024_t *dev = (im1024_t *)pgc;
|
||||
#endif
|
||||
int16_t x0, y0;
|
||||
int16_t x1, y1;
|
||||
int16_t x2, y2;
|
||||
int16_t y;
|
||||
|
||||
if (! pgc_param_word(pgc, &x0)) return;
|
||||
if (! pgc_param_word(pgc, &y0)) return;
|
||||
if (! pgc_param_word(pgc, &x1)) return;
|
||||
if (! pgc_param_word(pgc, &y1)) return;
|
||||
if (! pgc_param_word(pgc, &x2)) return;
|
||||
if (! pgc_param_word(pgc, &y2)) return;
|
||||
|
||||
DEBUG("BLKMOV %d,%d,%d,%d,%d,%d\n", x0, y0, x1, y1, x2, y2);
|
||||
|
||||
/* Disable clipping. */
|
||||
PUSHCLIP
|
||||
|
||||
/* Either go down from the top, or up from the bottom, depending
|
||||
* whether areas might overlap */
|
||||
if (y2 <= y0) {
|
||||
for (y = y0; y <= y1; y++)
|
||||
blkmov_row(pgc, x0, x1, x2, y, y - y0 + y2);
|
||||
} else {
|
||||
for (y = y1; y >= y0; y--)
|
||||
blkmov_row(pgc, x0, x1, x2, y, y - y0 + y2);
|
||||
}
|
||||
|
||||
/* Restore clipping. */
|
||||
POPCLIP
|
||||
}
|
||||
|
||||
|
||||
/* This overrides the PGC ELIPSE command to parse its parameters as words
|
||||
* rather than coordinates */
|
||||
static void
|
||||
hndl_ellipse(pgc_t *pgc)
|
||||
{
|
||||
int16_t x, y;
|
||||
|
||||
if (! pgc_param_word(pgc, &x)) return;
|
||||
if (! pgc_param_word(pgc, &y)) return;
|
||||
|
||||
DEBUG("ELLIPSE<IM1024> %d,%d @ %d,%d\n", x, y, pgc->x >> 16, pgc->y >> 16);
|
||||
|
||||
pgc_draw_ellipse(pgc, x << 16, y << 16);
|
||||
}
|
||||
|
||||
|
||||
/* This overrides the PGC MOVE command to parse its parameters as words
|
||||
* rather than coordinates */
|
||||
static void
|
||||
hndl_move(pgc_t *pgc)
|
||||
{
|
||||
int16_t x, y;
|
||||
|
||||
if (! pgc_param_word(pgc, &x)) return;
|
||||
if (! pgc_param_word(pgc, &y)) return;
|
||||
|
||||
pgc->x = x << 16;
|
||||
pgc->y = y << 16;
|
||||
|
||||
DEBUG("MOVE<IM1024> %d,%d\n", x, y);
|
||||
}
|
||||
|
||||
|
||||
/* This overrides the PGC DRAW command to parse its parameters as words
|
||||
* rather than coordinates */
|
||||
static void
|
||||
hndl_draw(pgc_t *pgc)
|
||||
{
|
||||
int16_t x, y;
|
||||
|
||||
if (! pgc_param_word(pgc, &x)) return;
|
||||
if (! pgc_param_word(pgc, &y)) return;
|
||||
|
||||
DEBUG("DRAW<IM1024> %d,%d to %d,%d\n", pgc->x >> 16, pgc->y >> 16, x, y);
|
||||
|
||||
pgc_draw_line(pgc, pgc->x, pgc->y, x << 16, y << 16, pgc->line_pattern);
|
||||
pgc->x = x << 16;
|
||||
pgc->y = y << 16;
|
||||
}
|
||||
|
||||
|
||||
/* This overrides the PGC POLY command to parse its parameters as words
|
||||
* rather than coordinates */
|
||||
static void
|
||||
hndl_poly(pgc_t *pgc)
|
||||
{
|
||||
int32_t *x, *y, *nx, *ny;
|
||||
int16_t xw, yw, mask;
|
||||
unsigned realcount = 0;
|
||||
unsigned n, as = 256;
|
||||
int parsing = 1;
|
||||
uint8_t count;
|
||||
|
||||
x = (int32_t *)mem_alloc(as * sizeof(int32_t));
|
||||
y = (int32_t *)mem_alloc(as * sizeof(int32_t));
|
||||
|
||||
if (!x || !y) {
|
||||
DEBUG("hndl_poly: malloc failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (parsing) {
|
||||
if (! pgc_param_byte(pgc, &count)) return;
|
||||
|
||||
if (count + realcount >= as) {
|
||||
nx = (int32_t *)realloc(x, 2 * as * sizeof(int32_t));
|
||||
ny = (int32_t *)realloc(y, 2 * as * sizeof(int32_t));
|
||||
if (!x || !y) {
|
||||
DEBUG("hndl_poly: realloc failed\n");
|
||||
break;
|
||||
}
|
||||
x = nx;
|
||||
y = ny;
|
||||
as *= 2;
|
||||
}
|
||||
|
||||
for (n = 0; n < count; n++) {
|
||||
if (! pgc_param_word(pgc, &xw)) return;
|
||||
if (! pgc_param_word(pgc, &yw)) return;
|
||||
|
||||
/* Skip degenerate line segments. */
|
||||
if (realcount > 0 &&
|
||||
(xw << 16) == x[realcount - 1] &&
|
||||
(yw << 16) == y[realcount - 1]) continue;
|
||||
|
||||
x[realcount] = xw << 16;
|
||||
y[realcount] = yw << 16;
|
||||
realcount++;
|
||||
}
|
||||
|
||||
/* If we are in a command list, peek ahead to see if the next
|
||||
* command is also POLY. If so, that's a continuation of this
|
||||
* polygon! */
|
||||
parsing = 0;
|
||||
if (pgc->clcur && (pgc->clcur->rdptr+1) < pgc->clcur->wrptr &&
|
||||
pgc->clcur->list[pgc->clcur->rdptr] == 0x30) {
|
||||
DEBUG("hndl_poly: POLY continues!\n");
|
||||
parsing = 1;
|
||||
|
||||
/* Swallow the POLY. */
|
||||
pgc->clcur->rdptr++;
|
||||
}
|
||||
};
|
||||
|
||||
DEBUG("POLY<IM1024> (%i) fill_mode=%d\n", realcount, pgc->fill_mode);
|
||||
for (n = 0; n < realcount; n++) {
|
||||
DEBUG(" (%i,%i)\n", x[n] >> 16, y[n] >> 16);
|
||||
}
|
||||
|
||||
if (pgc->fill_mode)
|
||||
pgc_fill_polygon(pgc, realcount, x, y);
|
||||
|
||||
/* Now draw borders. */
|
||||
mask = pgc->line_pattern;
|
||||
for (n = 1; n < realcount; n++)
|
||||
mask = pgc_draw_line(pgc, x[n - 1], y[n - 1], x[n], y[n], mask);
|
||||
pgc_draw_line(pgc, x[realcount - 1], y[realcount - 1], x[0], y[0], mask);
|
||||
|
||||
free(y);
|
||||
free(x);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
parse_poly(pgc_t *pgc, pgc_cl_t *cl, int c)
|
||||
{
|
||||
uint8_t count;
|
||||
|
||||
DEBUG("parse_poly<IM1024>\n");
|
||||
|
||||
if (! pgc_param_byte(pgc, &count)) return 0;
|
||||
|
||||
DEBUG("parse_poly<IM1024>: count=%02x\n", count);
|
||||
if (! pgc_commandlist_append(cl, count)) {
|
||||
pgc_error(pgc, PGC_ERROR_OVERFLOW);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG("parse_poly<IM1024>: parse %d words\n", 2 * count);
|
||||
|
||||
return pgc_parse_words(pgc, cl, count * 2);
|
||||
}
|
||||
|
||||
|
||||
/* This overrides the PGC RECT command to parse its parameters as words
|
||||
* rather than coordinates */
|
||||
static void
|
||||
hndl_rect(pgc_t *pgc)
|
||||
{
|
||||
int16_t x0, y0, x1, y1, p, q;
|
||||
|
||||
x0 = pgc->x >> 16;
|
||||
y0 = pgc->y >> 16;
|
||||
|
||||
if (! pgc_param_word(pgc, &x1)) return;
|
||||
if (! pgc_param_word(pgc, &y1)) return;
|
||||
|
||||
/* Convert to raster coords */
|
||||
pgc_sto_raster(pgc, &x0, &y0);
|
||||
pgc_sto_raster(pgc, &x1, &y1);
|
||||
|
||||
if (x0 > x1) { p = x0; x0 = x1; x1 = p; }
|
||||
if (y0 > y1) { q = y0; y0 = y1; y1 = q; }
|
||||
DEBUG("RECT<IM1024> (%d,%d) -> (%d,%d)\n", x0, y0, x1, y1);
|
||||
|
||||
if (pgc->fill_mode) {
|
||||
for (p = y0; p <= y1; p++)
|
||||
pgc_fill_line_r(pgc, x0, x1, p);
|
||||
} else {
|
||||
/* Outline: 4 lines */
|
||||
p = pgc->line_pattern;
|
||||
p = pgc_draw_line_r(pgc, x0, y0, x1, y0, p);
|
||||
p = pgc_draw_line_r(pgc, x1, y0, x1, y1, p);
|
||||
p = pgc_draw_line_r(pgc, x1, y1, x0, y1, p);
|
||||
p = pgc_draw_line_r(pgc, x0, y1, x0, y0, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Text drawing should probably be implemented in vid_pgc.c rather
|
||||
* than vid_im1024.c */
|
||||
static void
|
||||
hndl_tdefin(pgc_t *pgc)
|
||||
{
|
||||
im1024_t *dev = (im1024_t *)pgc;
|
||||
uint8_t ch, bt;
|
||||
uint8_t rows, cols;
|
||||
unsigned len, n;
|
||||
|
||||
if (! pgc_param_byte(pgc, &ch)) return;
|
||||
if (! pgc_param_byte(pgc, &rows)) return;
|
||||
if (! pgc_param_byte(pgc, &cols)) return;
|
||||
|
||||
DEBUG("TDEFIN<IM1024> (%d,%d,%d) 0x%02x 0x%02x\n",
|
||||
ch, rows, cols, pgc->mapram[0x300], pgc->mapram[0x301]);
|
||||
|
||||
len = ((cols + 7) / 8) * rows;
|
||||
for (n = 0; n < len; n++) {
|
||||
// char buf[10];
|
||||
|
||||
if (! pgc_param_byte(pgc, &bt)) return;
|
||||
|
||||
// buf[0] = 0;
|
||||
// for (mask = 0x80; mask != 0; mask >>= 1) {
|
||||
// if (bt & mask) strcat(buf, "#");
|
||||
// else strcat(buf, "-");
|
||||
// ++x;
|
||||
// if (x == cols) { strcat(buf, "\n"); x = 0; }
|
||||
// }
|
||||
// DEBUG(buf);
|
||||
|
||||
if (n < sizeof(dev->font[ch]))
|
||||
dev->font[ch][n] = bt;
|
||||
}
|
||||
|
||||
dev->fontx[ch] = rows;
|
||||
dev->fonty[ch] = cols;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hndl_twrite(pgc_t *pgc)
|
||||
{
|
||||
uint8_t buf[256], rbuf[256];
|
||||
im1024_t *dev = (im1024_t *)pgc;
|
||||
uint8_t count, mask, *row;
|
||||
int x, y, wb, n;
|
||||
int16_t x0 = pgc->x >> 16;
|
||||
int16_t y0 = pgc->y >> 16;
|
||||
|
||||
if (! pgc_param_byte(pgc, &count)) return;
|
||||
|
||||
for (n = 0; n < count; n++)
|
||||
if (! pgc_param_byte(pgc, &buf[n])) return;
|
||||
|
||||
buf[count] = 0;
|
||||
for (n = 0; n <= count; n++) {
|
||||
if (isprint(buf[n]) || 0 == buf[n])
|
||||
rbuf[n] = buf[n];
|
||||
else
|
||||
rbuf[n] = '?';
|
||||
}
|
||||
|
||||
pgc_sto_raster(pgc, &x0, &y0);
|
||||
DEBUG("TWRITE<IM1024> (%d,%-*.*s) x0=%d y0=%d\n",
|
||||
count, count, count, rbuf, x0, y0);
|
||||
|
||||
for (n = 0; n < count; n++) {
|
||||
wb = (dev->fontx[buf[n]] + 7) / 8;
|
||||
DEBUG("ch=0x%02x w=%d h=%d wb=%d\n",
|
||||
buf[n], dev->fontx[buf[n]], dev->fonty[buf[n]], wb);
|
||||
|
||||
for (y = 0; y < dev->fonty[buf[n]]; y++) {
|
||||
mask = 0x80;
|
||||
row = &dev->font[buf[n]][y * wb];
|
||||
for (x = 0; x < dev->fontx[buf[n]]; x++) {
|
||||
rbuf[x] = (row[0] & mask) ? '#' : '-';
|
||||
if (row[0] & mask)
|
||||
pgc_plot(pgc, x + x0, y0 - y);
|
||||
mask = mask >> 1;
|
||||
if (mask == 0) {
|
||||
mask = 0x80;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
rbuf[x++] = '\n';
|
||||
rbuf[x++] = 0;
|
||||
// DEBUG(rbuf);
|
||||
}
|
||||
|
||||
x0 += dev->fontx[buf[n]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
hndl_imagew(pgc_t *pgc)
|
||||
{
|
||||
int16_t vp_x1, vp_y1, vp_x2, vp_y2;
|
||||
int16_t row1, col1, col2;
|
||||
uint8_t v1, v2;
|
||||
|
||||
if (! pgc_param_word(pgc, &row1)) return;
|
||||
if (! pgc_param_word(pgc, &col1)) return;
|
||||
if (! pgc_param_word(pgc, &col2)) return;
|
||||
|
||||
/* IMAGEW already uses raster coordinates so there is no need to
|
||||
* convert it */
|
||||
DEBUG("IMAGEW<IM1024> (row=%d,col1=%d,col2=%d)\n", row1, col1, col2);
|
||||
|
||||
vp_x1 = pgc->vp_x1;
|
||||
vp_y1 = pgc->vp_y1;
|
||||
vp_x2 = pgc->vp_x2;
|
||||
vp_y2 = pgc->vp_y2;
|
||||
/* Disable clipping */
|
||||
pgc->vp_x1 = 0;
|
||||
pgc->vp_y1 = 0;
|
||||
pgc->vp_x2 = pgc->maxw - 1;
|
||||
pgc->vp_y2 = pgc->maxh - 1;
|
||||
|
||||
/* In ASCII mode, what is written is a stream of bytes */
|
||||
if (pgc->ascii_mode) {
|
||||
while (col1 <= col2) {
|
||||
if (! pgc_param_byte(pgc, &v1))
|
||||
return;
|
||||
|
||||
pgc_write_pixel(pgc, col1, row1, v1);
|
||||
col1++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* In hex mode, it's RLE compressed */
|
||||
while (col1 <= col2) {
|
||||
if (! pgc_param_byte(pgc, &v1)) return;
|
||||
|
||||
if (v1 & 0x80) {
|
||||
/* Literal run */
|
||||
v1 -= 0x7f;
|
||||
while (col1 <= col2 && v1 != 0) {
|
||||
if (! pgc_param_byte(pgc, &v2)) return;
|
||||
pgc_write_pixel(pgc, col1, row1, v2);
|
||||
col1++;
|
||||
v1--;
|
||||
}
|
||||
} else {
|
||||
/* Repeated run */
|
||||
if (! pgc_param_byte(pgc, &v2)) return;
|
||||
|
||||
v1++;
|
||||
while (col1 <= col2 && v1 != 0) {
|
||||
pgc_write_pixel(pgc, col1, row1, v2);
|
||||
col1++;
|
||||
v1--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore clipping */
|
||||
pgc->vp_x1 = vp_x1;
|
||||
pgc->vp_y1 = vp_y1;
|
||||
pgc->vp_x2 = vp_x2;
|
||||
pgc->vp_y2 = vp_y2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* I have called this command DOT - I don't know its proper name.
|
||||
*
|
||||
* Draws a single pixel at the current location.
|
||||
*/
|
||||
static void
|
||||
hndl_dot(pgc_t *pgc)
|
||||
{
|
||||
int16_t x = pgc->x >> 16, y = pgc->y >> 16;
|
||||
|
||||
pgc_sto_raster(pgc, &x, &y);
|
||||
|
||||
DEBUG("Dot @ %d,%d ink=%d mode=%d\n", x, y, pgc->colour, pgc->draw_mode);
|
||||
|
||||
pgc_plot(pgc, x, y);
|
||||
}
|
||||
|
||||
|
||||
/* This command (which I have called IMAGEX, since I don't know its real
|
||||
* name) is a screen-to-memory blit. It reads a rectangle of bytes, rather
|
||||
* than the single row read by IMAGER, and does not attempt to compress
|
||||
* the result */
|
||||
static void
|
||||
hndl_imagex(pgc_t *pgc)
|
||||
{
|
||||
int16_t x0, x1, y0, y1;
|
||||
int16_t p,q;
|
||||
|
||||
if (! pgc_param_word(pgc, &x0)) return;
|
||||
if (! pgc_param_word(pgc, &y0)) return;
|
||||
if (! pgc_param_word(pgc, &x1)) return;
|
||||
if (! pgc_param_word(pgc, &y1)) return;
|
||||
|
||||
/* IMAGEX already uses raster coordinates so don't convert */
|
||||
DEBUG("IMAGEX<IM1024> (%d,%d,%d,%d)\n", x0,y0,x1,y1);
|
||||
|
||||
for (p = y0; p <= y1; p++) {
|
||||
for (q = x0; q <= x1; q++) {
|
||||
if (! pgc_result_byte(pgc, pgc_read_pixel(pgc, q, p)))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Commands implemented by the IM-1024.
|
||||
*
|
||||
* TODO: A lot of commands need commandlist parsers.
|
||||
* TODO: The IM-1024 has a lot more commands that are not included here
|
||||
* (BLINK, BUTRD, COPROC, RBAND etc) because the Windows 1.03 driver
|
||||
* does not use them.
|
||||
*/
|
||||
static const pgc_cmd_t im1024_commands[] = {
|
||||
{ "BLKMOV", 0xdf, hndl_blkmov, pgc_parse_words, 6 },
|
||||
{ "DRAW", 0x28, hndl_draw, pgc_parse_words, 2 },
|
||||
{ "D", 0x28, hndl_draw, pgc_parse_words, 2 },
|
||||
{ "DOT", 0x08, hndl_dot, NULL, 0 },
|
||||
{ "ELIPSE", 0x39, hndl_ellipse, pgc_parse_words, 2 },
|
||||
{ "EL", 0x39, hndl_ellipse, pgc_parse_words, 2 },
|
||||
{ "IMAGEW", 0xd9, hndl_imagew, NULL, 0 },
|
||||
{ "IW", 0xd9, hndl_imagew, NULL, 0 },
|
||||
{ "IMAGEX", 0xda, hndl_imagex, NULL, 0 },
|
||||
{ "TWRITE", 0x8b, hndl_twrite, NULL, 0 },
|
||||
{ "TDEFIN", 0x84, hndl_tdefin, NULL, 0 },
|
||||
{ "TD", 0x84, hndl_tdefin, NULL, 0 },
|
||||
{ "IPREC", 0xe4, hndl_iprec, NULL, 0 },
|
||||
{ "IMGSIZ", 0x4e, hndl_imgsiz, NULL, 0 },
|
||||
{ "LUT8", 0xe6, pgc_hndl_lut8, NULL, 0 },
|
||||
{ "L8", 0xe6, pgc_hndl_lut8, NULL, 0 },
|
||||
{ "LUT8RD", 0x53, pgc_hndl_lut8rd,NULL, 0 },
|
||||
{ "L8RD", 0x53, pgc_hndl_lut8rd,NULL, 0 },
|
||||
{ "PAN", 0xb7, hndl_pan, NULL, 0 },
|
||||
{ "POLY", 0x30, hndl_poly, parse_poly, 0 },
|
||||
{ "P", 0x30, hndl_poly, parse_poly, 0 },
|
||||
{ "PLINE", 0x36, hndl_pline, NULL, 0 },
|
||||
{ "PL", 0x37, hndl_pline, NULL, 0 },
|
||||
{ "MOVE", 0x10, hndl_move, pgc_parse_words, 2 },
|
||||
{ "M", 0x10, hndl_move, pgc_parse_words, 2 },
|
||||
{ "RECT", 0x34, hndl_rect, NULL, 0 },
|
||||
{ "R", 0x34, hndl_rect, NULL, 0 },
|
||||
{ "******", 0x00, NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
static void *
|
||||
im1024_init(const device_t *info)
|
||||
{
|
||||
im1024_t *dev;
|
||||
|
||||
dev = (im1024_t *)mem_alloc(sizeof(im1024_t));
|
||||
memset(dev, 0x00, sizeof(im1024_t));
|
||||
|
||||
dev->fifo = (uint8_t *)mem_alloc(4096);
|
||||
dev->fifo_len = 4096;
|
||||
dev->fifo_wrptr = 0;
|
||||
dev->fifo_rdptr = 0;
|
||||
|
||||
/* Create a 1024x1024 framebuffer with 1024x800 visible. */
|
||||
pgc_init(&dev->pgc, 1024, 1024, 1024, 800, input_byte);
|
||||
|
||||
dev->pgc.commands = im1024_commands;
|
||||
|
||||
mem_map_set_handler(&dev->pgc.mapping,
|
||||
im1024_read,NULL,NULL, im1024_write,NULL,NULL);
|
||||
|
||||
video_inform(VID_TYPE_CGA, info->vid_timing);
|
||||
|
||||
return(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
im1024_close(void *priv)
|
||||
{
|
||||
im1024_t *dev = (im1024_t *)priv;
|
||||
|
||||
pgc_close(&dev->pgc);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static int
|
||||
im1024_available(void)
|
||||
{
|
||||
return rom_present(BIOS_ROM_PATH);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
speed_changed(void *priv)
|
||||
{
|
||||
im1024_t *dev = (im1024_t *)priv;
|
||||
|
||||
pgc_speed_changed(&dev->pgc);
|
||||
}
|
||||
|
||||
|
||||
static const video_timings_t im1024_timings = { VID_ISA,8,16,32,8,16,32 };
|
||||
|
||||
static const device_config_t im1024_config[] = {
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const device_t im1024_device = {
|
||||
"ImageManager 1024",
|
||||
DEVICE_ISA,
|
||||
0,
|
||||
im1024_init, im1024_close, NULL,
|
||||
NULL,
|
||||
speed_changed,
|
||||
NULL,
|
||||
&im1024_timings,
|
||||
im1024_config
|
||||
};
|
||||
2543
src/devices/video/vid_pgc.c
Normal file
2543
src/devices/video/vid_pgc.c
Normal file
File diff suppressed because it is too large
Load Diff
193
src/devices/video/vid_pgc.h
Normal file
193
src/devices/video/vid_pgc.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* VARCem Virtual ARchaeological Computer EMulator.
|
||||
* An emulator of (mostly) x86-based PC systems and devices,
|
||||
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
||||
* spanning the era between 1981 and 1995.
|
||||
*
|
||||
* This file is part of the VARCem Project.
|
||||
*
|
||||
* Definitions for the PGC driver.
|
||||
*
|
||||
* Version: @(#)vid_pgc.h 1.0.1 2019/03/01
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* John Elliott, <jce@seasip.info>
|
||||
*
|
||||
* Copyright 2019 Fred N. van Kempen.
|
||||
* Copyright 2019 John Elliott.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the:
|
||||
*
|
||||
* Free Software Foundation, Inc.
|
||||
* 59 Temple Place - Suite 330
|
||||
* Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
#ifndef VID_PGC_H
|
||||
# define VID_PGC_H
|
||||
|
||||
|
||||
#define PGC_ERROR_RANGE 0x01
|
||||
#define PGC_ERROR_INTEGER 0x02
|
||||
#define PGC_ERROR_MEMORY 0x03
|
||||
#define PGC_ERROR_OVERFLOW 0x04
|
||||
#define PGC_ERROR_DIGIT 0x05
|
||||
#define PGC_ERROR_OPCODE 0x06
|
||||
#define PGC_ERROR_RUNNING 0x07
|
||||
#define PGC_ERROR_STACK 0x08
|
||||
#define PGC_ERROR_TOOLONG 0x09
|
||||
#define PGC_ERROR_AREA 0x0A
|
||||
#define PGC_ERROR_MISSING 0x0B
|
||||
|
||||
|
||||
struct pgc;
|
||||
|
||||
typedef struct pgc_cl {
|
||||
uint8_t *list;
|
||||
uint32_t listmax;
|
||||
uint32_t wrptr;
|
||||
uint32_t rdptr;
|
||||
uint32_t repeat;
|
||||
struct pgc_cl *chain;
|
||||
} pgc_cl_t;
|
||||
|
||||
typedef struct pgc_cmd {
|
||||
char ascii[6];
|
||||
uint8_t hex;
|
||||
void (*handler)(struct pgc *);
|
||||
int (*parser) (struct pgc *, pgc_cl_t *, int);
|
||||
int p;
|
||||
} pgc_cmd_t;
|
||||
|
||||
typedef struct pgc {
|
||||
int type; /* board type */
|
||||
|
||||
mem_map_t mapping;
|
||||
mem_map_t cga_mapping;
|
||||
|
||||
pgc_cl_t *clist,
|
||||
*clcur;
|
||||
const pgc_cmd_t *commands;
|
||||
|
||||
uint8_t mapram[2048]; /* Host <--> PGC communication buffer */
|
||||
uint8_t *cga_vram;
|
||||
uint8_t *vram;
|
||||
char asc_command[7];
|
||||
uint8_t hex_command;
|
||||
uint32_t palette[256];
|
||||
uint32_t userpal[256];
|
||||
uint32_t maxw, maxh; /* Maximum framebuffer size */
|
||||
uint32_t visw, vish; /* Maximum screen size */
|
||||
uint32_t screenw, screenh;
|
||||
int16_t pan_x, pan_y;
|
||||
uint16_t win_x1, win_x2, win_y1, win_y2;
|
||||
uint16_t vp_x1, vp_x2, vp_y1, vp_y2;
|
||||
int16_t fill_pattern[16];
|
||||
int16_t line_pattern;
|
||||
uint8_t draw_mode;
|
||||
uint8_t fill_mode;
|
||||
uint8_t colour;
|
||||
uint8_t tjust_h; /* hor alignment 1=left 2=center 3=right*/
|
||||
uint8_t tjust_v; /* vert alignment 1=bottom 2=center 3=top*/
|
||||
|
||||
int32_t x, y, z; /* drawing position */
|
||||
|
||||
thread_t *pgc_thread;
|
||||
event_t *pgc_wake_thread;
|
||||
int64_t wake_timer;
|
||||
|
||||
int waiting_input_fifo;
|
||||
int waiting_output_fifo;
|
||||
int waiting_error_fifo;
|
||||
int cga_enabled;
|
||||
int cga_selected;
|
||||
int ascii_mode;
|
||||
int result_count;
|
||||
|
||||
int fontbase;
|
||||
int linepos, displine;
|
||||
int vc;
|
||||
int cgadispon;
|
||||
int con, coff, cursoron, cgablink;
|
||||
int vsynctime, vadj;
|
||||
uint16_t ma, maback;
|
||||
int oddeven;
|
||||
|
||||
int dispontime, dispofftime;
|
||||
int64_t vidtime;
|
||||
|
||||
int drawcursor;
|
||||
|
||||
int (*inputbyte)(struct pgc *, uint8_t *result);
|
||||
} pgc_t;
|
||||
|
||||
|
||||
/* I/O functions and worker thread handlers. */
|
||||
extern void pgc_out(uint16_t addr, uint8_t val, void *priv);
|
||||
extern uint8_t pgc_in(uint16_t addr, void *priv);
|
||||
extern void pgc_write(uint32_t addr, uint8_t val, void *priv);
|
||||
extern uint8_t pgc_read(uint32_t addr, void *priv);
|
||||
extern void pgc_recalctimings(pgc_t *);
|
||||
extern void pgc_poll(void *priv);
|
||||
extern void pgc_reset(pgc_t *);
|
||||
extern void pgc_wake(pgc_t *);
|
||||
extern void pgc_sleep(pgc_t *);
|
||||
extern void pgc_close(void *priv);
|
||||
extern void pgc_speed_changed(void *priv);
|
||||
extern void pgc_init(pgc_t *,
|
||||
int maxw, int maxh, int visw, int vish,
|
||||
int (*inpbyte)(pgc_t *, uint8_t *));
|
||||
|
||||
/* Misc support functions. */
|
||||
extern uint8_t *pgc_vram_addr(pgc_t *, int16_t x, int16_t y);
|
||||
extern void pgc_sto_raster(pgc_t *, int16_t *x, int16_t *y);
|
||||
extern void pgc_ito_raster(pgc_t *, int32_t *x, int32_t *y);
|
||||
extern void pgc_dto_raster(pgc_t *, double *x, double *y);
|
||||
//extern int pgc_input_byte(pgc_t *, uint8_t *val);
|
||||
//extern int pgc_output_byte(pgc_t *, uint8_t val);
|
||||
extern int pgc_output_string(pgc_t *, const char *val);
|
||||
//extern int pgc_error_byte(pgc_t *, uint8_t val);
|
||||
extern int pgc_error_string(pgc_t *, const char *val);
|
||||
extern int pgc_error(pgc_t *, int err);
|
||||
|
||||
/* Graphics functions. */
|
||||
extern void pgc_plot(pgc_t *, uint16_t x, uint16_t y);
|
||||
extern void pgc_write_pixel(pgc_t *, uint16_t x, uint16_t y, uint8_t ink);
|
||||
extern uint8_t pgc_read_pixel(pgc_t *, uint16_t x, uint16_t y);
|
||||
extern uint16_t pgc_draw_line(pgc_t *, int32_t x1, int32_t y1,
|
||||
int32_t x2, int32_t y2, uint16_t linemask);
|
||||
extern uint16_t pgc_draw_line_r(pgc_t *, int32_t x1, int32_t y1,
|
||||
int32_t x2, int32_t y2, uint16_t linemask);
|
||||
extern void pgc_draw_ellipse(pgc_t *, int32_t x, int32_t y);
|
||||
extern void pgc_fill_polygon(pgc_t *,
|
||||
unsigned corners, int32_t *x, int32_t *y);
|
||||
extern void pgc_fill_line_r(pgc_t *, int32_t x0, int32_t x1, int32_t y);
|
||||
|
||||
/* Command and parameter handling functions. */
|
||||
extern int pgc_commandlist_append(pgc_cl_t *, uint8_t v);
|
||||
extern int pgc_parse_bytes(pgc_t *, pgc_cl_t *, int p);
|
||||
extern int pgc_parse_words(pgc_t *, pgc_cl_t *, int p);
|
||||
extern int pgc_parse_coords(pgc_t *, pgc_cl_t *, int p);
|
||||
extern int pgc_param_byte(pgc_t *, uint8_t *val);
|
||||
extern int pgc_param_word(pgc_t *, int16_t *val);
|
||||
extern int pgc_param_coord(pgc_t *, int32_t *val);
|
||||
extern int pgc_result_byte(pgc_t *, uint8_t val);
|
||||
extern int pgc_result_word(pgc_t *, int16_t val);
|
||||
extern int pgc_result_coord(pgc_t *, int32_t val);
|
||||
|
||||
extern void pgc_hndl_lut8(pgc_t *);
|
||||
extern void pgc_hndl_lut8rd(pgc_t *);
|
||||
|
||||
|
||||
#endif /*VID_PGC_H*/
|
||||
1597
src/devices/video/vid_pgc_palette.h
Normal file
1597
src/devices/video/vid_pgc_palette.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,13 +8,13 @@
|
||||
*
|
||||
* Definitions for the video controller module.
|
||||
*
|
||||
* Version: @(#)video.h 1.0.25 2019/02/10
|
||||
* Version: @(#)video.h 1.0.26 2019/03/01
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||
*
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
*
|
||||
@@ -169,6 +169,9 @@ extern const device_t mach64vt2_device;
|
||||
/* IBM CGA and compatibles. */
|
||||
extern const device_t cga_device;
|
||||
|
||||
/* IBM PGC. */
|
||||
extern const device_t pgc_device;
|
||||
|
||||
/* Cirrus Logic GD-series cards. */
|
||||
#if defined(DEV_BRANCH)
|
||||
extern const device_t gd5402_isa_device;
|
||||
@@ -217,6 +220,9 @@ extern const device_t et4000w32p_cardex_pci_device;
|
||||
/* MDSI Genius VHR card. */
|
||||
extern const device_t genius_device;
|
||||
|
||||
/* ImageManager 1024 card. */
|
||||
extern const device_t im1024_device;
|
||||
|
||||
/* Hercules series cards and compatibles. */
|
||||
extern const device_t hercules_device;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* "extern" reference to its device into the video.h file,
|
||||
* and add an entry for it into the table here.
|
||||
*
|
||||
* Version: @(#)video_dev.c 1.0.30 2019/02/10
|
||||
* Version: @(#)video_dev.c 1.0.31 2019/03/01
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -102,6 +102,10 @@ static const struct {
|
||||
{ "hercules_plus", &herculesplus_device },
|
||||
{ "incolor", &incolor_device },
|
||||
{ "genius", &genius_device },
|
||||
#if 0
|
||||
{ "pgc", &pgc_device },
|
||||
#endif
|
||||
{ "im1024", &im1024_device },
|
||||
{ "oti037c", &oti037c_device },
|
||||
{ "oti067", &oti067_device },
|
||||
{ "oti077", &oti077_device },
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# Makefile for Windows systems using the MinGW32 environment.
|
||||
#
|
||||
# Version: @(#)Makefile.mingw 1.0.76 2019/02/13
|
||||
# Version: @(#)Makefile.mingw 1.0.77 2019/03/01
|
||||
#
|
||||
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
#
|
||||
@@ -717,6 +717,7 @@ VIDOBJ := video.o \
|
||||
vid_hercules.o vid_herculesplus.o vid_incolor.o \
|
||||
vid_colorplus.o \
|
||||
vid_genius.o \
|
||||
vid_pgc.o vid_im1024.o \
|
||||
vid_sigma.o \
|
||||
vid_wy700.o \
|
||||
vid_ega.o vid_ega_render.o \
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# Makefile for Windows using Visual Studio 2015.
|
||||
#
|
||||
# Version: @(#)Makefile.VC 1.0.62 2019/02/13
|
||||
# Version: @(#)Makefile.VC 1.0.63 2019/03/01
|
||||
#
|
||||
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
#
|
||||
@@ -693,6 +693,7 @@ VIDOBJ := video.obj \
|
||||
vid_hercules.obj vid_herculesplus.obj vid_incolor.obj \
|
||||
vid_colorplus.obj \
|
||||
vid_genius.obj \
|
||||
vid_pgc.obj vid_im1024.obj \
|
||||
vid_sigma.obj \
|
||||
vid_wy700.obj \
|
||||
vid_ega.obj vid_ega_render.obj \
|
||||
|
||||
Reference in New Issue
Block a user