mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 17:45:31 -07:00
1. The passthrough from VGA to 8514/A and/or 8514/A to VGA no longer relies on hackish places where to switch from/to, instead, relying on port 0x3c3 of VGA doing so (though the Mach8/32 still needs some places where to manually switch from/to, mainly the MCA one when configuring the EEPROM). 2. Implemented the MCA behalf of the Mach32 and its corresponding reset function. 3. Properly implemented (more or less) true color, including 24-bit BGR rendering 4. Other fixes such as color patterns and mono patterns being more correct than before in various operating systems and in 24-bit true color. 5. Implemented the onboard Mach32 video of the IBM PS/ValuePoint P60 machine. 6. Made the onboard internal video detect when it's 8514/A compatible or not (CGA/EGA/MDA/VGA/etc.). If the former is selected, then the video monitor flag is used instead (for QT). 7. The TGUI9400 and 9440, if on VLB, now detect the right amount of memory if on 2MB. 8. Initial implementation of the ATI 68875 ramdac used by the Mach32 and made the ATI 68860 8514/A aware when selected with the Mach32AX PCI. 9. Separated the 8514/A ramdac ports from the VGA ramdac ports, allowing seamless transition from/to 8514/A/VGA. 10. Fixed a hdisp problem in the ET4000/W32 cards, where it was doubling the horizontal display in 15bpp+ graphics mode. 11. Removed the 0x3da/0x3ba port hack that was on the Mach8/32 code, relying on the (S)VGA core instead. 12. Reworked and simplified the TGUI9440 pitch register based on logging due to no documentation at all.
437 lines
14 KiB
C
437 lines
14 KiB
C
/*
|
|
* 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.
|
|
*
|
|
* Generic SVGA handling.
|
|
*
|
|
*
|
|
*
|
|
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
|
* Miran Grca, <mgrca8@gmail.com>
|
|
*
|
|
* Copyright 2008-2020 Sarah Walker.
|
|
* Copyright 2016-2020 Miran Grca.
|
|
*/
|
|
|
|
#include <86box/thread.h>
|
|
#include <86box/vid_8514a.h>
|
|
#include <86box/vid_xga.h>
|
|
|
|
#ifndef VIDEO_SVGA_H
|
|
# define VIDEO_SVGA_H
|
|
|
|
# define FLAG_EXTRA_BANKS 1
|
|
# define FLAG_ADDR_BY8 2
|
|
# define FLAG_EXT_WRITE 4
|
|
# define FLAG_LATCH8 8
|
|
# define FLAG_NOSKEW 16
|
|
# define FLAG_ADDR_BY16 32
|
|
# define FLAG_RAMDAC_SHIFT 64
|
|
# define FLAG_ATI 128
|
|
# define FLAG_S3_911_16BIT 256
|
|
# define FLAG_512K_MASK 512
|
|
struct monitor_t;
|
|
|
|
typedef struct hwcursor_t {
|
|
int ena;
|
|
int x;
|
|
int y;
|
|
int xoff;
|
|
int yoff;
|
|
int cur_xsize;
|
|
int cur_ysize;
|
|
int v_acc;
|
|
int h_acc;
|
|
uint32_t addr;
|
|
uint32_t pitch;
|
|
} hwcursor_t;
|
|
|
|
typedef union {
|
|
uint64_t q;
|
|
uint32_t d[2];
|
|
uint16_t w[4];
|
|
uint8_t b[8];
|
|
} latch_t;
|
|
|
|
typedef struct svga_t {
|
|
ibm8514_t dev8514;
|
|
xga_t xga;
|
|
mem_mapping_t mapping;
|
|
|
|
uint8_t fast;
|
|
uint8_t chain4;
|
|
uint8_t chain2_write;
|
|
uint8_t chain2_read;
|
|
uint8_t ext_overscan;
|
|
uint8_t bus_size;
|
|
uint8_t lowres;
|
|
uint8_t interlace;
|
|
uint8_t linedbl;
|
|
uint8_t rowcount;
|
|
uint8_t set_reset_disabled;
|
|
uint8_t bpp;
|
|
uint8_t ramdac_type;
|
|
uint8_t fb_only;
|
|
uint8_t readmode;
|
|
uint8_t writemode;
|
|
uint8_t readplane;
|
|
uint8_t hwcursor_oddeven;
|
|
uint8_t dac_hwcursor_oddeven;
|
|
uint8_t overlay_oddeven;
|
|
uint8_t fcr;
|
|
uint8_t hblank_overscan;
|
|
|
|
int dac_addr;
|
|
int dac_pos;
|
|
int dac_r;
|
|
int dac_g;
|
|
int dac_b;
|
|
int vtotal;
|
|
int dispend;
|
|
int vsyncstart;
|
|
int split;
|
|
int vblankstart;
|
|
int hdisp;
|
|
int hdisp_old;
|
|
int htotal;
|
|
int hdisp_time;
|
|
int rowoffset;
|
|
int dispon;
|
|
int hdisp_on;
|
|
int vc;
|
|
int sc;
|
|
int linepos;
|
|
int vslines;
|
|
int linecountff;
|
|
int oddeven;
|
|
int con;
|
|
int cursoron;
|
|
int blink;
|
|
int scrollcache;
|
|
int char_width;
|
|
int firstline;
|
|
int lastline;
|
|
int firstline_draw;
|
|
int lastline_draw;
|
|
int displine;
|
|
int fullchange;
|
|
int x_add;
|
|
int y_add;
|
|
int pan;
|
|
int vram_display_mask;
|
|
int vidclock;
|
|
int dots_per_clock;
|
|
int hblank_ext;
|
|
int hwcursor_on;
|
|
int dac_hwcursor_on;
|
|
int overlay_on;
|
|
int set_override;
|
|
int hblankstart;
|
|
int hblankend;
|
|
int hblank_sub;
|
|
int hblank_end_val;
|
|
int hblank_end_len;
|
|
|
|
/*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 :
|
|
0MB-1MB - VRAM
|
|
1MB-2MB - VRAM mirror
|
|
2MB-4MB - open bus
|
|
4MB-xMB - mirror of above
|
|
|
|
For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB
|
|
(present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB)
|
|
*/
|
|
uint32_t decode_mask;
|
|
uint32_t vram_max;
|
|
uint32_t vram_mask;
|
|
uint32_t charseta;
|
|
uint32_t charsetb;
|
|
uint32_t adv_flags;
|
|
uint32_t ma_latch;
|
|
uint32_t ca_adj;
|
|
uint32_t ma;
|
|
uint32_t maback;
|
|
uint32_t write_bank;
|
|
uint32_t read_bank;
|
|
uint32_t extra_banks[2];
|
|
uint32_t banked_mask;
|
|
uint32_t ca;
|
|
uint32_t overscan_color;
|
|
uint32_t *map8;
|
|
uint32_t pallook[512];
|
|
|
|
PALETTE vgapal;
|
|
|
|
uint64_t dispontime;
|
|
uint64_t dispofftime;
|
|
latch_t latch;
|
|
|
|
pc_timer_t timer;
|
|
|
|
double clock;
|
|
|
|
hwcursor_t hwcursor;
|
|
hwcursor_t hwcursor_latch;
|
|
hwcursor_t dac_hwcursor;
|
|
hwcursor_t dac_hwcursor_latch;
|
|
hwcursor_t overlay;
|
|
hwcursor_t overlay_latch;
|
|
|
|
void (*render)(struct svga_t *svga);
|
|
void (*recalctimings_ex)(struct svga_t *svga);
|
|
|
|
void (*video_out)(uint16_t addr, uint8_t val, void *priv);
|
|
uint8_t (*video_in)(uint16_t addr, void *priv);
|
|
|
|
void (*hwcursor_draw)(struct svga_t *svga, int displine);
|
|
|
|
void (*dac_hwcursor_draw)(struct svga_t *svga, int displine);
|
|
|
|
void (*overlay_draw)(struct svga_t *svga, int displine);
|
|
|
|
void (*vblank_start)(struct svga_t *svga);
|
|
|
|
void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr);
|
|
float (*getclock)(int clock, void *priv);
|
|
|
|
/* Called when VC=R18 and friends. If this returns zero then MA resetting
|
|
is skipped. Matrox Mystique in Power mode reuses this counter for
|
|
vertical line interrupt*/
|
|
int (*line_compare)(struct svga_t *svga);
|
|
|
|
/*Called at the start of vertical sync*/
|
|
void (*vsync_callback)(struct svga_t *svga);
|
|
|
|
uint32_t (*translate_address)(uint32_t addr, void *priv);
|
|
/*If set then another device is driving the monitor output and the SVGA
|
|
card should not attempt to display anything */
|
|
int override;
|
|
void *priv;
|
|
|
|
uint8_t crtc[256];
|
|
uint8_t gdcreg[256];
|
|
uint8_t attrregs[32];
|
|
uint8_t seqregs[256];
|
|
uint8_t egapal[16];
|
|
uint8_t *vram;
|
|
uint8_t *changedvram;
|
|
|
|
uint8_t crtcreg;
|
|
uint8_t gdcaddr;
|
|
uint8_t attrff;
|
|
uint8_t attr_palette_enable;
|
|
uint8_t attraddr;
|
|
uint8_t seqaddr;
|
|
uint8_t miscout;
|
|
uint8_t cgastat;
|
|
uint8_t scrblank;
|
|
uint8_t plane_mask;
|
|
uint8_t writemask;
|
|
uint8_t colourcompare;
|
|
uint8_t colournocare;
|
|
uint8_t dac_mask;
|
|
uint8_t dac_status;
|
|
uint8_t dpms;
|
|
uint8_t dpms_ui;
|
|
uint8_t ksc5601_sbyte_mask;
|
|
uint8_t ksc5601_udc_area_msb[2];
|
|
|
|
int ksc5601_swap_mode;
|
|
uint16_t ksc5601_english_font_type;
|
|
|
|
int vertical_linedbl;
|
|
|
|
/*Used to implement CRTC[0x17] bit 2 hsync divisor*/
|
|
int hsync_divisor;
|
|
|
|
/*Tseng-style chain4 mode - CRTC dword mode is the same as byte mode, chain4
|
|
addresses are shifted to match*/
|
|
int packed_chain4;
|
|
|
|
/*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
|
|
int force_dword_mode;
|
|
|
|
int force_old_addr;
|
|
|
|
int remap_required;
|
|
uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr);
|
|
|
|
void *ramdac;
|
|
void *clock_gen;
|
|
|
|
/* Monitor Index */
|
|
uint8_t monitor_index;
|
|
|
|
/* Pointer to monitor */
|
|
monitor_t *monitor;
|
|
} svga_t;
|
|
|
|
extern int vga_on;
|
|
extern int ibm8514_on;
|
|
|
|
extern void ibm8514_poll(ibm8514_t *dev, svga_t *svga);
|
|
extern void ibm8514_recalctimings(svga_t *svga);
|
|
extern uint8_t ibm8514_ramdac_in(uint16_t port, void *priv);
|
|
extern void ibm8514_ramdac_out(uint16_t port, uint8_t val, void *priv);
|
|
extern int ibm8514_cpu_src(svga_t *svga);
|
|
extern int ibm8514_cpu_dest(svga_t *svga);
|
|
extern void ibm8514_accel_out_pixtrans(svga_t *svga, uint16_t port, uint16_t val, int len);
|
|
extern void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len);
|
|
extern void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len);
|
|
|
|
extern void xga_poll(xga_t *xga, svga_t *svga);
|
|
extern void xga_recalctimings(svga_t *svga);
|
|
|
|
extern int svga_init(const device_t *info, svga_t *svga, void *priv, int memsize,
|
|
void (*recalctimings_ex)(struct svga_t *svga),
|
|
uint8_t (*video_in)(uint16_t addr, void *priv),
|
|
void (*video_out)(uint16_t addr, uint8_t val, void *priv),
|
|
void (*hwcursor_draw)(struct svga_t *svga, int displine),
|
|
void (*overlay_draw)(struct svga_t *svga, int displine));
|
|
extern void svga_recalctimings(svga_t *svga);
|
|
extern void svga_close(svga_t *svga);
|
|
|
|
uint8_t svga_read(uint32_t addr, void *priv);
|
|
uint16_t svga_readw(uint32_t addr, void *priv);
|
|
uint32_t svga_readl(uint32_t addr, void *priv);
|
|
void svga_write(uint32_t addr, uint8_t val, void *priv);
|
|
void svga_writew(uint32_t addr, uint16_t val, void *priv);
|
|
void svga_writel(uint32_t addr, uint32_t val, void *priv);
|
|
uint8_t svga_read_linear(uint32_t addr, void *priv);
|
|
uint8_t svga_readb_linear(uint32_t addr, void *priv);
|
|
uint16_t svga_readw_linear(uint32_t addr, void *priv);
|
|
uint32_t svga_readl_linear(uint32_t addr, void *priv);
|
|
void svga_write_linear(uint32_t addr, uint8_t val, void *priv);
|
|
void svga_writeb_linear(uint32_t addr, uint8_t val, void *priv);
|
|
void svga_writew_linear(uint32_t addr, uint16_t val, void *priv);
|
|
void svga_writel_linear(uint32_t addr, uint32_t val, void *priv);
|
|
|
|
void svga_add_status_info(char *s, int max_len, void *priv);
|
|
|
|
extern uint8_t svga_rotate[8][256];
|
|
|
|
void svga_out(uint16_t addr, uint8_t val, void *priv);
|
|
uint8_t svga_in(uint16_t addr, void *priv);
|
|
|
|
svga_t *svga_get_pri(void);
|
|
void svga_set_override(svga_t *svga, int val);
|
|
|
|
void svga_set_ramdac_type(svga_t *svga, int type);
|
|
void svga_close(svga_t *svga);
|
|
|
|
uint32_t svga_mask_addr(uint32_t addr, svga_t *svga);
|
|
uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga);
|
|
|
|
void svga_doblit(int wx, int wy, svga_t *svga);
|
|
|
|
enum {
|
|
RAMDAC_6BIT = 0,
|
|
RAMDAC_8BIT
|
|
};
|
|
|
|
/* We need a way to add a device with a pointer to a parent device so it can attach itself to it, and
|
|
possibly also a second ATi 68860 RAM DAC type that auto-sets SVGA render on RAM DAC render change. */
|
|
extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga);
|
|
extern void ati68860_set_ramdac_type(void *priv, int type);
|
|
extern void ati68860_ramdac_set_render(void *priv, svga_t *svga);
|
|
extern void ati68860_ramdac_set_pallook(void *priv, int i, uint32_t col);
|
|
extern void ati68860_hwcursor_draw(svga_t *svga, int displine);
|
|
|
|
extern void ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga);
|
|
|
|
extern void att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t att49x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga);
|
|
|
|
extern void att498_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t att498_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga);
|
|
extern float av9194_getclock(int clock, void *priv);
|
|
|
|
extern void bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga);
|
|
extern void bt48x_recalctimings(void *priv, svga_t *svga);
|
|
extern void bt48x_hwcursor_draw(svga_t *svga, int displine);
|
|
|
|
extern void ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga);
|
|
extern void ibm_rgb528_recalctimings(void *priv, svga_t *svga);
|
|
extern void ibm_rgb528_hwcursor_draw(svga_t *svga, int displine);
|
|
|
|
extern void icd2061_write(void *priv, int val);
|
|
extern float icd2061_getclock(int clock, void *priv);
|
|
|
|
/* The code is the same, the #define's are so that the correct name can be used. */
|
|
# define ics9161_write icd2061_write
|
|
# define ics9161_getclock icd2061_getclock
|
|
|
|
extern float ics2494_getclock(int clock, void *priv);
|
|
|
|
extern void ics2595_write(void *priv, int strobe, int dat);
|
|
extern double ics2595_getclock(void *priv);
|
|
extern void ics2595_setclock(void *priv, double clock);
|
|
|
|
extern void sc1148x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t sc1148x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga);
|
|
|
|
extern void sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t sc1502x_ramdac_in(uint16_t addr, void *priv, svga_t *svga);
|
|
|
|
extern void sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t sdac_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga);
|
|
extern float sdac_getclock(int clock, void *priv);
|
|
|
|
extern void stg_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t stg_ramdac_in(uint16_t addr, void *priv, svga_t *svga);
|
|
extern float stg_getclock(int clock, void *priv);
|
|
|
|
extern void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t tkd8001_ramdac_in(uint16_t addr, void *priv, svga_t *svga);
|
|
|
|
extern void tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga);
|
|
extern uint8_t tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga);
|
|
extern void tvp3026_recalctimings(void *priv, svga_t *svga);
|
|
extern void tvp3026_hwcursor_draw(svga_t *svga, int displine);
|
|
extern float tvp3026_getclock(int clock, void *priv);
|
|
|
|
# ifdef EMU_DEVICE_H
|
|
extern const device_t ati68860_ramdac_device;
|
|
extern const device_t ati68875_ramdac_device;
|
|
extern const device_t att490_ramdac_device;
|
|
extern const device_t att491_ramdac_device;
|
|
extern const device_t att492_ramdac_device;
|
|
extern const device_t att498_ramdac_device;
|
|
extern const device_t av9194_device;
|
|
extern const device_t bt484_ramdac_device;
|
|
extern const device_t att20c504_ramdac_device;
|
|
extern const device_t bt485_ramdac_device;
|
|
extern const device_t att20c505_ramdac_device;
|
|
extern const device_t bt485a_ramdac_device;
|
|
extern const device_t gendac_ramdac_device;
|
|
extern const device_t ibm_rgb528_ramdac_device;
|
|
extern const device_t ics2494an_305_device;
|
|
extern const device_t ati18810_device;
|
|
extern const device_t ati18811_0_device;
|
|
extern const device_t ati18811_1_device;
|
|
extern const device_t ics2595_device;
|
|
extern const device_t icd2061_device;
|
|
extern const device_t ics9161_device;
|
|
extern const device_t sc11483_ramdac_device;
|
|
extern const device_t sc11487_ramdac_device;
|
|
extern const device_t sc11486_ramdac_device;
|
|
extern const device_t sc11484_nors2_ramdac_device;
|
|
extern const device_t sc1502x_ramdac_device;
|
|
extern const device_t sdac_ramdac_device;
|
|
extern const device_t stg_ramdac_device;
|
|
extern const device_t tkd8001_ramdac_device;
|
|
extern const device_t tseng_ics5301_ramdac_device;
|
|
extern const device_t tseng_ics5341_ramdac_device;
|
|
extern const device_t tvp3026_ramdac_device;
|
|
# endif
|
|
|
|
#endif /*VIDEO_SVGA_H*/
|