#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "ibm.h"
#include "device.h"
#include "mem.h"
#include "video.h"
#include "vid_svga.h"
#include "io.h"
#include "cpu.h"
#include "rom.h"
#include "thread.h"
#include "timer.h"

#include "vid_ati18800.h"
#include "vid_ati28800.h"
#include "vid_ati_mach64.h"
#include "vid_cga.h"
#include "vid_cl5429.h"
#include "vid_compaq_cga.h"
#include "vid_ega.h"
#include "vid_et4000.h"
#include "vid_et4000w32.h"
#include "vid_genius.h"
#include "vid_hercules.h"
#include "vid_ht216.h"
#include "vid_im1024.h"
#include "vid_incolor.h"
#include "vid_colorplus.h"
#include "vid_mda.h"
#include "vid_mga.h"
#include "vid_olivetti_m24.h"
#include "vid_oti037.h"
#include "vid_oti067.h"
#include "vid_paradise.h"
#include "vid_pc1512.h"
#include "vid_pc1640.h"
#include "vid_pc200.h"
#include "vid_pcjr.h"
#include "vid_pgc.h"
#include "vid_ps1_svga.h"
#include "vid_s3.h"
#include "vid_s3_virge.h"
#include "vid_sigma.h"
#include "vid_tandy.h"
#include "vid_tandysl.h"
#include "vid_tgui9440.h"
#include "vid_tvga.h"
#include "vid_vga.h"
#include "vid_wy700.h"
#include "vid_t3100e.h"
#include "vid_t1000.h"
#include "vid_voodoo_banshee.h"

#include <pcem/devices.h>

extern VIDEO_CARD *video_cards[GFX_MAX];

enum {
	VIDEO_ISA = 0,
	VIDEO_BUS
};

#define VIDEO_FLAG_TYPE_CGA     0
#define VIDEO_FLAG_TYPE_MDA     1
#define VIDEO_FLAG_TYPE_SPECIAL 2
#define VIDEO_FLAG_TYPE_MASK    3

VIDEO_CARD v_banshee = {"3DFX Voodoo Banshee (reference)", "banshee", &voodoo_banshee_device, GFX_BANSHEE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}};
VIDEO_CARD v_v3_2000 = {"3DFX Voodoo 3 2000", "v3_2000", &voodoo_3_2000_device, GFX_VOODOO_3_2000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}};
VIDEO_CARD v_v3_3000 = {"3DFX Voodoo 3 3000", "v3_3000", &voodoo_3_3000_device, GFX_VOODOO_3_3000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}};
VIDEO_CARD v_avga2 = {"Acumos AVGA2 / Cirrus Logic CL-GD5402", "avga2", &avga2_device, GFX_AVGA2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}};
VIDEO_CARD v_mach64gx = {"ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx", &mach64gx_device, GFX_MACH64GX, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}};
VIDEO_CARD v_mach64vt2 = {"ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, GFX_MACH64VT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}};
VIDEO_CARD v_egawonder800 = {"ATI EGA Wonder 800+ (ATI-18800)", "egawonder800", &ati_ega_wonder_800_device, GFX_EGAWONDER800, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_ati28800k = {"ATI Korean VGA (ATI-28800)", "ati28800k", &ati28800k_device, GFX_ATIKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}};
VIDEO_CARD v_ati28800 = {"ATI VGA Charger (ATI-28800)", "ati28800", &ati28800_device, GFX_VGACHARGER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}};
VIDEO_CARD v_ati18800 = {"ATI VGA Edge-16 (ATI-18800)", "ati18800", &ati18800_device, GFX_VGAEDGE16, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_cga = {"CGA", "cga", &cga_device, GFX_CGA, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_cl_gd5428 = {"Cirrus Logic CL-GD5428", "cl_gd5428", &gd5428_device, GFX_CL_GD5428, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}};
VIDEO_CARD v_cl_gd5429 = {"Cirrus Logic CL-GD5429", "cl_gd5429", &gd5429_device, GFX_CL_GD5429, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}};
VIDEO_CARD v_cl_gd5430 = {"Cirrus Logic CL-GD5430", "cl_gd5430", &gd5430_device, GFX_CL_GD5430, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}};
VIDEO_CARD v_cl_gd5434 = {"Cirrus Logic CL-GD5434", "cl_gd5434", &gd5434_device, GFX_CL_GD5434, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}};
VIDEO_CARD v_compaq_cga_device = {"Compaq CGA", "compaq_cga", &compaq_cga_device, GFX_COMPAQ_CGA, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_cl_banshee = {"Creative Labs 3D Blaster Banshee PCI", "cl_banshee", &creative_voodoo_banshee_device, GFX_CL_BANSHEE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}};
VIDEO_CARD v_stealth32 = {"Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32", &et4000w32p_device, GFX_ET4000W32, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}};
VIDEO_CARD v_stealth3d_2000 = {"Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000", &s3_virge_device, GFX_VIRGE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}};
VIDEO_CARD v_ega = {"EGA", "ega", &ega_device, GFX_EGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_hercules = {"Hercules", "hercules", &hercules_device, GFX_HERCULES, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_incolor = {"Hercules InColor", "incolor", &incolor_device, GFX_INCOLOR, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_ibm1mbsvga = {"IBM 1MB SVGA Adapter/A (CL GD5428)", "ibm1mbsvga", &ibm_gd5428_device, GFX_IBM_GD5428, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}};
VIDEO_CARD v_im1024 = {"Image Manager 1024", "im1024", &im1024_device, GFX_IM1024, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_kasan16 = {"Kasan Hangulmadang-16 (Tseng ET4000AX)", "kasan16", &et4000_kasan_device, GFX_KASAN16VGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}};
VIDEO_CARD v_mystique = {"Matrox Mystique", "mystique", &mystique_device, GFX_MYSTIQUE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}};
VIDEO_CARD v_millennium = {"Matrox Millennium", "millennium", &millennium_device, GFX_MILLENNIUM, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 10, 10, 10}};
VIDEO_CARD v_mda = {"MDA", "mda", &mda_device, GFX_MDA, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_genius = {"MDSI Genius", "genius", &genius_device, GFX_GENIUS, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_n9_9fx = {"Number Nine 9FX (S3 Trio64)", "n9_9fx", &s3_9fx_device, GFX_N9_9FX, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}};
VIDEO_CARD v_oti037 = {"OAK OTI-037", "oti037", &oti037_device, GFX_OTI037, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}};
VIDEO_CARD v_oti067 = {"OAK OTI-067", "oti067", &oti067_device, GFX_OTI067, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}};
VIDEO_CARD v_olivetti_go481 = {"Olivetti GO481 (Paradise PVGA1A)", "olivetti_go481", &paradise_pvga1a_oli_go481_device, GFX_OLIVETTI_GO481, VIDEO_FLAG_TYPE_SPECIAL,
	{VIDEO_ISA, 6, 8, 16, 6, 8, 16}};
VIDEO_CARD v_bahamas64 = {"Paradise Bahamas 64 (S3 Vision864)", "bahamas64", &s3_bahamas64_device, GFX_BAHAMAS64, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}};
#ifdef USE_EXPERIMENTAL_PGC
VIDEO_CARD v_pgc = {"Professional Graphics Controller", "pgc", &pgc_device, GFX_PGC, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
#endif
VIDEO_CARD v_px_trio32 = {"Phoenix S3 Trio32", "px_trio32", &s3_phoenix_trio32_device, GFX_PHOENIX_TRIO32, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}};
VIDEO_CARD v_px_trio64 = {"Phoenix S3 Trio64", "px_trio64", &s3_phoenix_trio64_device, GFX_PHOENIX_TRIO64, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}};
VIDEO_CARD v_plantronics = {"Plantronics ColorPlus", "plantronics", &colorplus_device, GFX_COLORPLUS, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_virge375 = {"S3 ViRGE/DX", "virge375", &s3_virge_375_device, GFX_VIRGEDX, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}};
VIDEO_CARD v_sigma400 = {"Sigma Color 400", "sigma400", &sigma_device, GFX_SIGMA400, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_tvga8900d = {"Trident TVGA8900D", "tvga8900d", &tvga8900d_device, GFX_TVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}};
VIDEO_CARD v_tvga9000b = {"Trident TVGA9000B", "tvga9000b", &tvga9000b_device, GFX_TVGA9000B, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 7, 7, 12, 7, 7, 12}};
VIDEO_CARD v_tgui9400cxi = {"Trident TGUI9400CXi", "tgui9400cxi", &tgui9400cxi_device, GFX_TGUI9400CXI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}};
VIDEO_CARD v_tgui9440 = {"Trident TGUI9440", "tgui9440", &tgui9440_device, GFX_TGUI9440, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}};
VIDEO_CARD v_tgkorvga = {"Trigem Korean VGA (Tseng ET4000AX)", "tgkorvga", &et4000k_device, GFX_TGKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}};
VIDEO_CARD v_et4000ax = {"Tseng ET4000AX", "et4000ax", &et4000_device, GFX_ET4000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}};
VIDEO_CARD v_vga = {"VGA", "vga", &vga_device, GFX_VGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};
VIDEO_CARD v_wy700 = {"Wyse 700", "wy700", &wy700_device, GFX_WY700, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}};

static video_timings_t timing_dram = {VIDEO_BUS, 0, 0, 0, 0, 0, 0}; /*No additional waitstates*/
static video_timings_t timing_pc1512 = {VIDEO_BUS, 0, 0, 0, 0, 0, 0}; /*PC1512 video code handles waitstates itself*/
static video_timings_t timing_pc1640 = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_pc200 = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_m24 = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_pvga1a = {VIDEO_ISA, 6, 8, 16, 6, 8, 16};
static video_timings_t timing_wd90c11 = {VIDEO_ISA, 3, 3, 6, 5, 5, 10};
static video_timings_t timing_avga2 = {VIDEO_ISA, 3, 3, 6, 5, 5, 10};
static video_timings_t timing_oti067 = {VIDEO_ISA, 6, 8, 16, 6, 8, 16};
static video_timings_t timing_vga = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_ps1_svga = {VIDEO_ISA, 6, 8, 16, 6, 8, 16};
static video_timings_t timing_t3100e = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_t1000 = {VIDEO_ISA, 8, 16, 32, 8, 16, 32};
static video_timings_t timing_spc4620p = {VIDEO_ISA, 2, 2, 4, 4, 4, 8};
static video_timings_t timing_pc425x = {VIDEO_BUS, 5, 5, 9, 20, 20, 30};
static video_timings_t timing_pb410a = {VIDEO_BUS, 5, 5, 9, 20, 20, 30};
static video_timings_t timing_pb570 = {VIDEO_BUS, 4, 4, 8, 10, 10, 20};
static video_timings_t timing_pb520r = {VIDEO_BUS, 4, 4, 8, 10, 10, 20};

int video_card_available(int card) {
	if (card == GFX_BUILTIN)
		return 1;

	if (video_cards[card]->device)
		return device_available(video_cards[card]->device);

	return 1;
}

char *video_card_getname(int card) {
	if (card == GFX_BUILTIN)
		return "Built-in video";
	if (video_cards[card] == NULL)
		return "";

	return video_cards[card]->name;
}

device_t *video_card_getdevice(int card, int romset) {
	switch (romset) {
	case ROM_IBMPCJR:return &pcjr_video_device;

	case ROM_TANDY:
	case ROM_TANDY1000HX:return &tandy_device;

	case ROM_TANDY1000SL2:return &tandysl_device;

	case ROM_PC1512:return &pc1512_device;

	case ROM_PC1640:
		if (card == GFX_BUILTIN)
			return &pc1640_device;
		break;

	case ROM_PC200:
		if (card == GFX_BUILTIN)
			return &pc200_device;
		break;

	case ROM_PPC512:
		if (card == GFX_BUILTIN)
			return &ppc512_device;
		break;

	case ROM_OLIM24:return &m24_device;

	case ROM_PC2086:
		if (card == GFX_BUILTIN)
			return &paradise_pvga1a_pc2086_device;
		break;

	case ROM_PC3086:
		if (card == GFX_BUILTIN)
			return &paradise_pvga1a_pc3086_device;
		break;

	case ROM_MEGAPC:return &paradise_wd90c11_megapc_device;

	case ROM_SPC4620P:
		if (card == GFX_BUILTIN)
			return &ati28800k_spc4620p_device;
		break;

	case ROM_SPC6033P:
		if (card == GFX_BUILTIN)
			return &ati28800k_spc6033p_device;
		break;

	case ROM_ACER386:return &oti067_acer386_device;

	case ROM_AMA932J:return &oti067_ama932j_device;

	case ROM_IBMPS1_2011:
	case ROM_IBMPS2_M30_286:return &ps1vga_device;

	case ROM_IBMPS2_M50:
	case ROM_IBMPS2_M55SX:
	case ROM_IBMPS2_M70_TYPE3:
	case ROM_IBMPS2_M70_TYPE4:
	case ROM_IBMPS2_M80:
		if (card == GFX_BUILTIN)
			return &ps1vga_device;
		break;

	case ROM_IBMPS1_2121:return &ps1_m2121_svga_device;

	case ROM_IBMPS1_2133_451:return &gd5426_ps1_device;

	case ROM_T3100E:return &t3100e_device;

	case ROM_T1000:
	case ROM_T1200:return &t1000_device;

	case ROM_ELX_PC425X:return &tgui9400cxi_elx_device;

	case ROM_PB410A:return &ht216_32_pb410a_device;

	case ROM_PB570:return &gd5430_pb570_device;

	case ROM_PB520R:return &gd5434_pb520r_device;

	case ROM_CBM_SL386SX25:return &avga2_cbm_sl386sx_device;
	}
	return video_cards[card]->device;
}

int video_card_has_config(int card, int romset) {
	/* Allow builtin cards to have configuration */
	device_t *device = video_card_getdevice(card, romset);

	if (!device) {
		return 0;
	}
	return device->config ? 1 : 0;
}

int video_card_getid(char *s) {
	int c = 0;

	while (video_cards[c] != NULL && video_cards[c]->device) {
		if (!strcmp(video_cards[c]->name, s))
			return c;
		c++;
	}

	if (!strcmp(s, "Built-in video"))
		return GFX_BUILTIN;

	return 0;
}

int video_old_to_new(int card) {
	int c = 0;

	if (card == GFX_BUILTIN)
		return GFX_BUILTIN;

	while (video_cards[c] != NULL && video_cards[c]->device) {
		if (video_cards[c]->legacy_id == card)
			return c;
		c++;
	}

	return 0;
}

int video_new_to_old(int card) {
	if (card == GFX_BUILTIN)
		return GFX_BUILTIN;

	return video_cards[card]->legacy_id;
}

char *video_get_internal_name(int card) {
	if (card == GFX_BUILTIN)
		return "builtin";

	return video_cards[card]->internal_name;
}

int video_get_video_from_internal_name(char *s) {
	int c = 0;

	if (!strcmp(s, "builtin"))
		return GFX_BUILTIN;

	while (video_cards[c] != NULL) {
		if (!strcmp(video_cards[c]->internal_name, s))
			return video_cards[c]->legacy_id;
		c++;
	}

	return 0;
}

int video_is_mda() {
	switch (romset) {
	case ROM_PC200:
	case ROM_PPC512:
		if (gfxcard == GFX_BUILTIN) {
/* The chipset here can emulate either CGA or MDA. Find out which */
			return (pc200_is_mda);
		}
		break;

	case ROM_PC1640:
	case ROM_PC2086:
	case ROM_PC3086:
	case ROM_MEGAPC:
	case ROM_ACER386:
		if (gfxcard != GFX_BUILTIN)
			break;
	case ROM_IBMPCJR:
	case ROM_TANDY:
	case ROM_TANDY1000HX:
	case ROM_TANDY1000SL2:
	case ROM_PC1512:
	case ROM_OLIM24:
	case ROM_IBMPS1_2011:
	case ROM_IBMPS2_M30_286:
	case ROM_IBMPS2_M50:
	case ROM_IBMPS2_M55SX:
	case ROM_IBMPS2_M70_TYPE3:
	case ROM_IBMPS2_M70_TYPE4:
	case ROM_IBMPS2_M80:
	case ROM_IBMPS1_2121:
	case ROM_IBMPS1_2133_451:
	case ROM_T3100E:
	case ROM_T1000:
	case ROM_ELX_PC425X:
	case ROM_PB410A:
	case ROM_PB570:
	case ROM_PB520R:
	case ROM_CBM_SL386SX25:return 0;
	}
	return (video_cards[video_old_to_new(gfxcard)]->flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_MDA;
}
int video_is_cga() {
	switch (romset) {
	case ROM_PC200:
	case ROM_PPC512:
		if (gfxcard == GFX_BUILTIN) {
/* The chipset here can emulate either CGA or MDA. Find out which */
			return (!pc200_is_mda);
		}
		break;

	case ROM_IBMPCJR:
	case ROM_TANDY:
	case ROM_TANDY1000HX:
	case ROM_TANDY1000SL2:
	case ROM_PC1512:
	case ROM_OLIM24:
	case ROM_T3100E:
	case ROM_T1000:return 1;

	case ROM_PC1640:
	case ROM_PC2086:
	case ROM_PC3086:
	case ROM_MEGAPC:
	case ROM_ACER386:
		if (gfxcard != GFX_BUILTIN)
			break;
	case ROM_IBMPS1_2011:
	case ROM_IBMPS2_M30_286:
	case ROM_IBMPS2_M50:
	case ROM_IBMPS2_M55SX:
	case ROM_IBMPS2_M70_TYPE3:
	case ROM_IBMPS2_M70_TYPE4:
	case ROM_IBMPS2_M80:
	case ROM_IBMPS1_2121:
	case ROM_IBMPS1_2133_451:
	case ROM_ELX_PC425X:
	case ROM_PB410A:
	case ROM_PB570:
	case ROM_PB520R:
	case ROM_CBM_SL386SX25:return 0;
	}
	return (video_cards[video_old_to_new(gfxcard)]->flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_CGA;
}
int video_is_ega_vga() {
	switch (romset) {
	case ROM_IBMPCJR:
	case ROM_TANDY:
	case ROM_TANDY1000HX:
	case ROM_TANDY1000SL2:
	case ROM_PC1512:
	case ROM_PC200:
	case ROM_PPC512:
	case ROM_OLIM24:
	case ROM_T3100E:
	case ROM_T1000:return 0;

	case ROM_PC1640:
	case ROM_PC2086:
	case ROM_PC3086:
	case ROM_MEGAPC:
	case ROM_ACER386:
	case ROM_AMA932J:
	case ROM_IBMPS1_2011:
	case ROM_IBMPS2_M30_286:
	case ROM_IBMPS2_M50:
	case ROM_IBMPS2_M55SX:
	case ROM_IBMPS2_M70_TYPE3:
	case ROM_IBMPS2_M70_TYPE4:
	case ROM_IBMPS2_M80:
	case ROM_IBMPS1_2121:
	case ROM_IBMPS1_2133_451:
	case ROM_ELX_PC425X:
	case ROM_PB410A:
	case ROM_PB570:
	case ROM_PB520R:
	case ROM_CBM_SL386SX25:return 1;
	}
	return (video_cards[video_old_to_new(gfxcard)]->flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_SPECIAL;
}

int video_fullscreen = 0, video_fullscreen_scale, video_fullscreen_first;
int video_force_aspect_ration = 0;
int vid_disc_indicator = 0;

uint32_t *video_15to32, *video_16to32;

int egareads = 0, egawrites = 0;
int changeframecount = 2;

uint8_t rotatevga[8][256];

int frames = 0;
int video_frames = 0;
int video_refresh_rate = 0;

int fullchange;

uint8_t edatlookup[4][4];

/*Video timing settings -

8-bit - 1mb/sec
        B = 8 ISA clocks
        W = 16 ISA clocks
        L = 32 ISA clocks
        
Slow 16-bit - 2mb/sec
        B = 6 ISA clocks
        W = 8 ISA clocks
        L = 16 ISA clocks

Fast 16-bit - 4mb/sec
        B = 3 ISA clocks
        W = 3 ISA clocks
        L = 6 ISA clocks
        
Slow VLB/PCI - 8mb/sec (ish)
        B = 4 bus clocks
        W = 8 bus clocks
        L = 16 bus clocks
        
Mid VLB/PCI -
        B = 4 bus clocks
        W = 5 bus clocks
        L = 10 bus clocks
        
Fast VLB/PCI -
        B = 3 bus clocks
        W = 3 bus clocks
        L = 4 bus clocks
*/

int video_speed = 0;
int video_timing[7][4] =
	{
		{VIDEO_ISA, 8, 16, 32},
		{VIDEO_ISA, 6, 8, 16},
		{VIDEO_ISA, 3, 3, 6},
		{VIDEO_BUS, 4, 8, 16},
		{VIDEO_BUS, 4, 5, 10},
		{VIDEO_BUS, 3, 3, 4}
	};

void video_updatetiming() {
	if (video_speed == -1) {
		video_timings_t *timing;
		int new_gfxcard = 0;

		new_gfxcard = video_old_to_new(gfxcard);
		timing = &video_cards[new_gfxcard]->timing;

		switch (romset) {
		case ROM_IBMPCJR:
		case ROM_TANDY:
		case ROM_TANDY1000HX:
		case ROM_TANDY1000SL2:timing = &timing_dram;
			break;

		case ROM_PC1512:timing = &timing_pc1512;
			break;

		case ROM_PC1640:
			if (gfxcard == GFX_BUILTIN)
				timing = &timing_pc1640;
			break;

		case ROM_PC200:
		case ROM_PPC512:
			if (gfxcard == GFX_BUILTIN)
				timing = &timing_pc200;
			break;

		case ROM_OLIM24:timing = &timing_m24;
			break;

		case ROM_PC2086:
		case ROM_PC3086:
			if (gfxcard == GFX_BUILTIN)
				timing = &timing_pvga1a;
			break;

		case ROM_MEGAPC:
			if (gfxcard == GFX_BUILTIN)
				timing = &timing_wd90c11;
			break;

		case ROM_SPC4620P:
		case ROM_SPC6033P:
			if (gfxcard == GFX_BUILTIN)
				timing = &timing_spc4620p;
			break;

		case ROM_ACER386:
			if (gfxcard == GFX_BUILTIN)
				timing = &timing_oti067;
			break;

		case ROM_AMA932J:
			if (gfxcard == GFX_BUILTIN)
				timing = &timing_oti067;
			break;

		case ROM_IBMPS1_2011:
		case ROM_IBMPS2_M30_286:timing = &timing_vga;
			break;

		case ROM_IBMPS2_M50:
		case ROM_IBMPS2_M55SX:
		case ROM_IBMPS2_M70_TYPE3:
		case ROM_IBMPS2_M70_TYPE4:
		case ROM_IBMPS2_M80:
			if (gfxcard == GFX_BUILTIN)
				timing = &timing_vga;
			break;

		case ROM_IBMPS1_2121:timing = &timing_ps1_svga;
			break;

		case ROM_IBMPS1_2133_451:timing = &timing_pb570;
			break;

		case ROM_T3100E:timing = &timing_t3100e;
			break;

		case ROM_T1000:timing = &timing_t1000;
			break;

		case ROM_ELX_PC425X:timing = &timing_pc425x;
			break;

		case ROM_PB410A:
			if (gfxcard == GFX_BUILTIN)
				timing = &timing_pb410a;
			break;

		case ROM_PB570:timing = &timing_pb570;
			break;

		case ROM_PB520R:timing = &timing_pb520r;
			break;

		case ROM_CBM_SL386SX25:timing = &timing_avga2;
			break;
		}

		if (timing->type == VIDEO_ISA) {
			video_timing_read_b = ISA_CYCLES(timing->read_b);
			video_timing_read_w = ISA_CYCLES(timing->read_w);
			video_timing_read_l = ISA_CYCLES(timing->read_l);
			video_timing_write_b = ISA_CYCLES(timing->write_b);
			video_timing_write_w = ISA_CYCLES(timing->write_w);
			video_timing_write_l = ISA_CYCLES(timing->write_l);
		} else {
			video_timing_read_b = (int)(bus_timing * timing->read_b);
			video_timing_read_w = (int)(bus_timing * timing->read_w);
			video_timing_read_l = (int)(bus_timing * timing->read_l);
			video_timing_write_b = (int)(bus_timing * timing->write_b);
			video_timing_write_w = (int)(bus_timing * timing->write_w);
			video_timing_write_l = (int)(bus_timing * timing->write_l);
		}
	} else {
		if (video_timing[video_speed][0] == VIDEO_ISA) {
			video_timing_read_b = ISA_CYCLES(video_timing[video_speed][1]);
			video_timing_read_w = ISA_CYCLES(video_timing[video_speed][2]);
			video_timing_read_l = ISA_CYCLES(video_timing[video_speed][3]);
			video_timing_write_b = ISA_CYCLES(video_timing[video_speed][1]);
			video_timing_write_w = ISA_CYCLES(video_timing[video_speed][2]);
			video_timing_write_l = ISA_CYCLES(video_timing[video_speed][3]);
		} else {
			video_timing_read_b = (int)(bus_timing * video_timing[video_speed][1]);
			video_timing_read_w = (int)(bus_timing * video_timing[video_speed][2]);
			video_timing_read_l = (int)(bus_timing * video_timing[video_speed][3]);
			video_timing_write_b = (int)(bus_timing * video_timing[video_speed][1]);
			video_timing_write_w = (int)(bus_timing * video_timing[video_speed][2]);
			video_timing_write_l = (int)(bus_timing * video_timing[video_speed][3]);
		}
	}
	pclog("Video timing %i %i %i\n", video_timing_write_b, video_timing_write_w, video_timing_write_l);
	if (cpu_16bitbus) {
		video_timing_read_l = video_timing_read_w * 2;
		video_timing_write_l = video_timing_write_w * 2;
	}
}

int video_timing_read_b, video_timing_read_w, video_timing_read_l;
int video_timing_write_b, video_timing_write_w, video_timing_write_l;

int video_res_x, video_res_y, video_bpp;

void (*video_blit_memtoscreen_func)(int x, int y, int y1, int y2, int w, int h);

void video_init() {
	pclog("Video_init %i %i\n", romset, gfxcard);

	switch (romset) {
	case ROM_IBMPCJR:device_add(&pcjr_video_device);
		return;

	case ROM_TANDY:
	case ROM_TANDY1000HX:device_add(&tandy_device);
		return;

	case ROM_TANDY1000SL2:device_add(&tandysl_device);
		return;

	case ROM_PC1512:device_add(&pc1512_device);
		return;

	case ROM_PC1640:
		if (gfxcard == GFX_BUILTIN) {
			device_add(&pc1640_device);
			return;
		}
		break;

	case ROM_PC200:
		if (gfxcard == GFX_BUILTIN) {
			device_add(&pc200_device);
			return;
		}
		break;

	case ROM_PPC512:
		if (gfxcard == GFX_BUILTIN) {
			device_add(&ppc512_device);
			return;
		}
		break;

	case ROM_OLIM24:device_add(&m24_device);
		return;

	case ROM_PC2086:
		if (gfxcard == GFX_BUILTIN) {
			device_add(&paradise_pvga1a_pc2086_device);
			return;
		}
		break;

	case ROM_PC3086:
		if (gfxcard == GFX_BUILTIN) {
			device_add(&paradise_pvga1a_pc3086_device);
			return;
		}
		break;

	case ROM_MEGAPC:
		if (gfxcard == GFX_BUILTIN) {
			device_add(&paradise_wd90c11_megapc_device);
			return;
		}
		break;

	case ROM_SPC4620P:
		if (gfxcard == GFX_BUILTIN) {
			device_add(&ati28800k_spc4620p_device);
			return;
		}
		break;

	case ROM_SPC6033P:
		if (gfxcard == GFX_BUILTIN) {
			device_add(&ati28800k_spc6033p_device);
			return;
		}
		break;

	case ROM_ACER386:device_add(&oti067_acer386_device);
		if (gfxcard != GFX_BUILTIN) {
			svga_set_override(svga_get_pri(), 1);
			break;
		}
		return;

	case ROM_AMA932J:device_add(&oti067_ama932j_device);
		return;

	case ROM_IBMPS1_2011:
	case ROM_IBMPS2_M30_286:device_add(&ps1vga_device);
		return;

	case ROM_IBMPS2_M50:
	case ROM_IBMPS2_M55SX:
	case ROM_IBMPS2_M70_TYPE3:
	case ROM_IBMPS2_M70_TYPE4:
	case ROM_IBMPS2_M80:device_add(&ps1vga_device);
		if (gfxcard == GFX_BUILTIN)
			return;
		break;

	case ROM_IBMPS1_2121:device_add(&ps1_m2121_svga_device);
		return;

	case ROM_IBMPS1_2133_451:device_add(&gd5426_ps1_device);
		return;

	case ROM_T3100E:device_add(&t3100e_device);
		return;

	case ROM_T1000:
	case ROM_T1200:device_add(&t1000_device);
		return;

	case ROM_ELX_PC425X:device_add(&tgui9400cxi_elx_device);
		return;

	case ROM_PB410A:device_add(&ht216_32_pb410a_device);
		if (gfxcard != GFX_BUILTIN) {
			svga_set_override(svga_get_pri(), 1);
			break;
		}
		return;

	case ROM_PB570:device_add(&gd5430_pb570_device);
		if (gfxcard != GFX_BUILTIN) {
			svga_set_override(svga_get_pri(), 1);
			break;
		}
		return;

	case ROM_PB520R:device_add(&gd5434_pb520r_device);
		if (gfxcard != GFX_BUILTIN) {
			svga_set_override(svga_get_pri(), 1);
			break;
		}
		return;

	case ROM_CBM_SL386SX25:device_add(&avga2_cbm_sl386sx_device);
		return;
	}
	device_add(video_cards[video_old_to_new(gfxcard)]->device);
}

BITMAP *buffer32;

uint8_t fontdat[2048][8];
uint8_t fontdatm[2048][16];
uint8_t fontdatw[512][32];        /* Wyse700 font */
uint8_t fontdat8x12[256][16];        /* MDSI Genius font */
uint8_t fontdat12x18[256][36];        /* IM1024 font */
uint8_t fontdatksc5601[16384][32]; /* Korean KSC-5601 font */
uint8_t fontdatksc5601_user[192][32]; /* Korean KSC-5601 user defined font */

int xsize = 1, ysize = 1;

void loadfont(char *s, fontformat_t format) {
	FILE *f = romfopen(s, "rb");
	int c, d;

	pclog("loadfont %i %s %p\n", format, s, f);
	if (!f) {
		return;
	}
	switch (format) {
	case FONT_MDA:        /* MDA */
		for (c = 0; c < 256; c++) {
			for (d = 0; d < 8; d++) {
				fontdatm[c][d] = getc(f);
			}
		}
		for (c = 0; c < 256; c++) {
			for (d = 0; d < 8; d++) {
				fontdatm[c][d + 8] = getc(f);
			}
		}
		fseek(f, 4096 + 2048, SEEK_SET);
		for (c = 0; c < 256; c++) {
			for (d = 0; d < 8; d++) {
				fontdat[c][d] = getc(f);
			}
		}
		break;
	case FONT_PC200:        /* PC200 */
		for (d = 0; d < 4; d++)        /* There are 4 fonts in the ROM */
		{
			for (c = 0; c < 256; c++)        /* 8x14 MDA in 8x16 cell */
			{
				fread(&fontdatm[256 * d + c], 1, 16, f);
			}
			for (c = 0; c < 256; c++)        /* 8x8 CGA in 8x16 cell */
			{
				fread(fontdat[256 * d + c], 1, 8, f);
				fseek(f, 8, SEEK_CUR);
			}
		}
		break;
	default:
	case FONT_CGA:        /* CGA */
		for (c = 0; c < 2048; c++)        /* Allow up to 2048 chars */
		{
			for (d = 0; d < 8; d++) {
				fontdat[c][d] = getc(f);
			}
		}
		break;
	case FONT_WY700: /* Wyse 700 */
		for (c = 0; c < 512; c++) {
			for (d = 0; d < 32; d++) {
				fontdatw[c][d] = getc(f);
			}
		}
		break;
	case FONT_MDSI: /* MDSI Genius */
		for (c = 0; c < 256; c++) {
			for (d = 0; d < 16; d++) {
				fontdat8x12[c][d] = getc(f);
			}
		}
		break;
	case FONT_T3100E: /* Toshiba 3100e */
		for (d = 0; d < 2048; d += 512)        /* Four languages... */
		{
			for (c = d; c < d + 256; c++) {
				fread(&fontdatm[c][8], 1, 8, f);
			}
			for (c = d + 256; c < d + 512; c++) {
				fread(&fontdatm[c][8], 1, 8, f);
			}
			for (c = d; c < d + 256; c++) {
				fread(&fontdatm[c][0], 1, 8, f);
			}
			for (c = d + 256; c < d + 512; c++) {
				fread(&fontdatm[c][0], 1, 8, f);
			}
			fseek(f, 4096, SEEK_CUR);        /* Skip blank section */
			for (c = d; c < d + 256; c++) {
				fread(&fontdat[c][0], 1, 8, f);
			}
			for (c = d + 256; c < d + 512; c++) {
				fread(&fontdat[c][0], 1, 8, f);
			}
		}
		break;
	case FONT_KSC5601: /* Korean KSC-5601 */
		for (c = 0; c < 16384; c++) {
			for (d = 0; d < 32; d++) {
				fontdatksc5601[c][d] = getc(f);
			}
		}
		break;
	case FONT_SIGMA400: /* Sigma Color 400 */
		/* The first 4k of the character ROM holds an 8x8 font */
		for (c = 0; c < 256; c++) {
			fread(&fontdat[c][0], 1, 8, f);
			fseek(f, 8, SEEK_CUR);
		}
		/* The second 4k holds an 8x16 font */
		for (c = 0; c < 256; c++) {
			fread(&fontdatm[c][0], 1, 16, f);
		}
		break;
	case FONT_IM1024: /* Image Manager 1024 native font */
		for (c = 0; c < 256; c++) {
			fread(&fontdat12x18[c][0], 1, 36, f);
		}
		break;

	}
	fclose(f);
}

static struct {
	int x, y, y1, y2, w, h;
	int busy;
	int buffer_in_use;

	thread_t *blit_thread;
	event_t *wake_blit_thread;
	event_t *blit_complete;
	event_t *buffer_not_in_use;
} blit_data;

static void blit_thread(void *param);

uint32_t cgapal[16];

void initvideo() {
	int c, d, e;

	buffer32 = create_bitmap(2048, 2048);

	for (c = 0; c < 256; c++) {
		e = c;
		for (d = 0; d < 8; d++) {
			rotatevga[d][c] = e;
			e = (e >> 1) | ((e & 1) ? 0x80 : 0);
		}
	}
	for (c = 0; c < 4; c++) {
		for (d = 0; d < 4; d++) {
			edatlookup[c][d] = 0;
			if (c & 1)
				edatlookup[c][d] |= 1;
			if (d & 1)
				edatlookup[c][d] |= 2;
			if (c & 2)
				edatlookup[c][d] |= 0x10;
			if (d & 2)
				edatlookup[c][d] |= 0x20;
//                        printf("Edat %i,%i now %02X\n",c,d,edatlookup[c][d]);
		}
	}

	video_15to32 = malloc(4 * 65536);
	for (c = 0; c < 65536; c++)
		video_15to32[c] = ((c & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 10) & 31) << 19);

	video_16to32 = malloc(4 * 65536);
	for (c = 0; c < 65536; c++)
		video_16to32[c] = ((c & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 11) & 31) << 19);

	cgapal_rebuild(DISPLAY_RGB, 0);

	blit_data.wake_blit_thread = thread_create_event();
	blit_data.blit_complete = thread_create_event();
	blit_data.buffer_not_in_use = thread_create_event();
	blit_data.blit_thread = thread_create(blit_thread, NULL);
}

void closevideo() {
	thread_kill(blit_data.blit_thread);
	thread_destroy_event(blit_data.buffer_not_in_use);
	thread_destroy_event(blit_data.blit_complete);
	thread_destroy_event(blit_data.wake_blit_thread);

	free(video_15to32);
	free(video_16to32);
	destroy_bitmap(buffer32);
}

static void blit_thread(void *param) {
	while (1) {
		thread_wait_event(blit_data.wake_blit_thread, -1);
		thread_reset_event(blit_data.wake_blit_thread);

		video_blit_memtoscreen_func(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h);

		blit_data.busy = 0;
		thread_set_event(blit_data.blit_complete);
	}
}

void video_blit_complete() {
	blit_data.buffer_in_use = 0;
	thread_set_event(blit_data.buffer_not_in_use);
}

void video_wait_for_blit() {
	while (blit_data.busy)
		thread_wait_event(blit_data.blit_complete, 1);
	thread_reset_event(blit_data.blit_complete);
}
void video_wait_for_buffer() {
	while (blit_data.buffer_in_use)
		thread_wait_event(blit_data.buffer_not_in_use, 1);
	thread_reset_event(blit_data.buffer_not_in_use);
}

void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) {
	video_frames++;
	if (h <= 0)
		return;
	video_wait_for_blit();
	blit_data.busy = 1;
	blit_data.buffer_in_use = 1;
	blit_data.x = x;
	blit_data.y = y;
	blit_data.y1 = y1;
	blit_data.y2 = y2;
	blit_data.w = w;
	blit_data.h = h;
	thread_set_event(blit_data.wake_blit_thread);
}

void cgapal_rebuild(int display_type, int contrast) {
	switch (display_type) {
	case DISPLAY_GREEN:
		if (contrast) {
			cgapal[0x0] = makecol(0x00, 0x00, 0x00);
			cgapal[0x1] = makecol(0x00, 0x34, 0x0c);
			cgapal[0x2] = makecol(0x04, 0x5d, 0x14);
			cgapal[0x3] = makecol(0x04, 0x69, 0x18);
			cgapal[0x4] = makecol(0x08, 0xa2, 0x24);
			cgapal[0x5] = makecol(0x08, 0xb2, 0x28);
			cgapal[0x6] = makecol(0x0c, 0xe7, 0x34);
			cgapal[0x7] = makecol(0x0c, 0xf3, 0x38);
			cgapal[0x8] = makecol(0x00, 0x1c, 0x04);
			cgapal[0x9] = makecol(0x04, 0x4d, 0x10);
			cgapal[0xa] = makecol(0x04, 0x7d, 0x1c);
			cgapal[0xb] = makecol(0x04, 0x8e, 0x20);
			cgapal[0xc] = makecol(0x08, 0xc7, 0x2c);
			cgapal[0xd] = makecol(0x08, 0xd7, 0x30);
			cgapal[0xe] = makecol(0x14, 0xff, 0x45);
			cgapal[0xf] = makecol(0x34, 0xff, 0x5d);
		} else {
			cgapal[0x0] = makecol(0x00, 0x00, 0x00);
			cgapal[0x1] = makecol(0x00, 0x34, 0x0c);
			cgapal[0x2] = makecol(0x04, 0x55, 0x14);
			cgapal[0x3] = makecol(0x04, 0x5d, 0x14);
			cgapal[0x4] = makecol(0x04, 0x86, 0x20);
			cgapal[0x5] = makecol(0x04, 0x92, 0x20);
			cgapal[0x6] = makecol(0x08, 0xba, 0x2c);
			cgapal[0x7] = makecol(0x08, 0xc7, 0x2c);
			cgapal[0x8] = makecol(0x04, 0x8a, 0x20);
			cgapal[0x9] = makecol(0x08, 0xa2, 0x24);
			cgapal[0xa] = makecol(0x08, 0xc3, 0x2c);
			cgapal[0xb] = makecol(0x08, 0xcb, 0x30);
			cgapal[0xc] = makecol(0x0c, 0xe7, 0x34);
			cgapal[0xd] = makecol(0x0c, 0xef, 0x38);
			cgapal[0xe] = makecol(0x24, 0xff, 0x51);
			cgapal[0xf] = makecol(0x34, 0xff, 0x5d);
		}
		break;
	case DISPLAY_AMBER:
		if (contrast) {
			cgapal[0x0] = makecol(0x00, 0x00, 0x00);
			cgapal[0x1] = makecol(0x55, 0x14, 0x00);
			cgapal[0x2] = makecol(0x82, 0x2c, 0x00);
			cgapal[0x3] = makecol(0x92, 0x34, 0x00);
			cgapal[0x4] = makecol(0xcf, 0x61, 0x00);
			cgapal[0x5] = makecol(0xdf, 0x6d, 0x00);
			cgapal[0x6] = makecol(0xff, 0x9a, 0x04);
			cgapal[0x7] = makecol(0xff, 0xae, 0x18);
			cgapal[0x8] = makecol(0x2c, 0x08, 0x00);
			cgapal[0x9] = makecol(0x6d, 0x20, 0x00);
			cgapal[0xa] = makecol(0xa6, 0x45, 0x00);
			cgapal[0xb] = makecol(0xba, 0x51, 0x00);
			cgapal[0xc] = makecol(0xef, 0x79, 0x00);
			cgapal[0xd] = makecol(0xfb, 0x86, 0x00);
			cgapal[0xe] = makecol(0xff, 0xcb, 0x28);
			cgapal[0xf] = makecol(0xff, 0xe3, 0x34);
		} else {
			cgapal[0x0] = makecol(0x00, 0x00, 0x00);
			cgapal[0x1] = makecol(0x55, 0x14, 0x00);
			cgapal[0x2] = makecol(0x79, 0x24, 0x00);
			cgapal[0x3] = makecol(0x86, 0x2c, 0x00);
			cgapal[0x4] = makecol(0xae, 0x49, 0x00);
			cgapal[0x5] = makecol(0xbe, 0x55, 0x00);
			cgapal[0x6] = makecol(0xe3, 0x71, 0x00);
			cgapal[0x7] = makecol(0xef, 0x79, 0x00);
			cgapal[0x8] = makecol(0xb2, 0x4d, 0x00);
			cgapal[0x9] = makecol(0xcb, 0x5d, 0x00);
			cgapal[0xa] = makecol(0xeb, 0x79, 0x00);
			cgapal[0xb] = makecol(0xf3, 0x7d, 0x00);
			cgapal[0xc] = makecol(0xff, 0x9e, 0x04);
			cgapal[0xd] = makecol(0xff, 0xaa, 0x10);
			cgapal[0xe] = makecol(0xff, 0xdb, 0x30);
			cgapal[0xf] = makecol(0xff, 0xe3, 0x34);
		}
		break;
	case DISPLAY_WHITE:
		if (contrast) {
			cgapal[0x0] = makecol(0x00, 0x00, 0x00);
			cgapal[0x1] = makecol(0x37, 0x3d, 0x40);
			cgapal[0x2] = makecol(0x55, 0x5c, 0x5f);
			cgapal[0x3] = makecol(0x61, 0x67, 0x6b);
			cgapal[0x4] = makecol(0x8f, 0x95, 0x95);
			cgapal[0x5] = makecol(0x9b, 0xa0, 0x9f);
			cgapal[0x6] = makecol(0xcc, 0xcf, 0xc8);
			cgapal[0x7] = makecol(0xdf, 0xde, 0xd4);
			cgapal[0x8] = makecol(0x24, 0x27, 0x29);
			cgapal[0x9] = makecol(0x42, 0x48, 0x4c);
			cgapal[0xa] = makecol(0x70, 0x76, 0x78);
			cgapal[0xb] = makecol(0x81, 0x87, 0x87);
			cgapal[0xc] = makecol(0xaf, 0xb3, 0xb0);
			cgapal[0xd] = makecol(0xbb, 0xbf, 0xba);
			cgapal[0xe] = makecol(0xef, 0xed, 0xdf);
			cgapal[0xf] = makecol(0xff, 0xfd, 0xed);
		} else {
			cgapal[0x0] = makecol(0x00, 0x00, 0x00);
			cgapal[0x1] = makecol(0x37, 0x3d, 0x40);
			cgapal[0x2] = makecol(0x4a, 0x50, 0x54);
			cgapal[0x3] = makecol(0x55, 0x5c, 0x5f);
			cgapal[0x4] = makecol(0x78, 0x7e, 0x80);
			cgapal[0x5] = makecol(0x81, 0x87, 0x87);
			cgapal[0x6] = makecol(0xa3, 0xa7, 0xa6);
			cgapal[0x7] = makecol(0xaf, 0xb3, 0xb0);
			cgapal[0x8] = makecol(0x7a, 0x81, 0x83);
			cgapal[0x9] = makecol(0x8c, 0x92, 0x92);
			cgapal[0xa] = makecol(0xac, 0xb0, 0xad);
			cgapal[0xb] = makecol(0xb3, 0xb7, 0xb4);
			cgapal[0xc] = makecol(0xd1, 0xd3, 0xcb);
			cgapal[0xd] = makecol(0xd9, 0xdb, 0xd2);
			cgapal[0xe] = makecol(0xf7, 0xf5, 0xe7);
			cgapal[0xf] = makecol(0xff, 0xfd, 0xed);
		}
		break;

	default:cgapal[0x0] = makecol(0x00, 0x00, 0x00);
		cgapal[0x1] = makecol(0x00, 0x00, 0xaa);
		cgapal[0x2] = makecol(0x00, 0xaa, 0x00);
		cgapal[0x3] = makecol(0x00, 0xaa, 0xaa);
		cgapal[0x4] = makecol(0xaa, 0x00, 0x00);
		cgapal[0x5] = makecol(0xaa, 0x00, 0xaa);
		if (display_type == DISPLAY_RGB_NO_BROWN) {
			cgapal[0x6] = makecol(0xaa, 0xaa, 0x00);
		} else {
			cgapal[0x6] = makecol(0xaa, 0x55, 0x00);
		}
		cgapal[0x7] = makecol(0xaa, 0xaa, 0xaa);
		cgapal[0x8] = makecol(0x55, 0x55, 0x55);
		cgapal[0x9] = makecol(0x55, 0x55, 0xff);
		cgapal[0xa] = makecol(0x55, 0xff, 0x55);
		cgapal[0xb] = makecol(0x55, 0xff, 0xff);
		cgapal[0xc] = makecol(0xff, 0x55, 0x55);
		cgapal[0xd] = makecol(0xff, 0x55, 0xff);
		cgapal[0xe] = makecol(0xff, 0xff, 0x55);
		cgapal[0xf] = makecol(0xff, 0xff, 0xff);
		break;
	}
}

void video_init_builtin() {
	pcem_add_video(&v_banshee);
	pcem_add_video(&v_v3_2000);
	pcem_add_video(&v_v3_3000);
	pcem_add_video(&v_avga2);
	pcem_add_video(&v_mach64gx);
	pcem_add_video(&v_mach64vt2);
	pcem_add_video(&v_egawonder800);
	pcem_add_video(&v_ati28800k);
	pcem_add_video(&v_ati28800);
	pcem_add_video(&v_ati18800);
	pcem_add_video(&v_cga);
	pcem_add_video(&v_cl_gd5428);
	pcem_add_video(&v_cl_gd5429);
	pcem_add_video(&v_cl_gd5430);
	pcem_add_video(&v_cl_gd5434);
	pcem_add_video(&v_compaq_cga_device);
	pcem_add_video(&v_cl_banshee);
	pcem_add_video(&v_stealth32);
	pcem_add_video(&v_stealth3d_2000);
	pcem_add_video(&v_ega);
	pcem_add_video(&v_hercules);
	pcem_add_video(&v_incolor);
	pcem_add_video(&v_ibm1mbsvga);
	pcem_add_video(&v_im1024);
	pcem_add_video(&v_kasan16);
	pcem_add_video(&v_mystique);
	pcem_add_video(&v_millennium);
	pcem_add_video(&v_mda);
	pcem_add_video(&v_genius);
	pcem_add_video(&v_n9_9fx);
	pcem_add_video(&v_oti037);
	pcem_add_video(&v_oti067);
	pcem_add_video(&v_olivetti_go481);
	pcem_add_video(&v_bahamas64);
#ifdef USE_EXPERIMENTAL_PGC
	pcem_add_video(&v_pgc);
#endif
	pcem_add_video(&v_px_trio32);
	pcem_add_video(&v_px_trio64);
	pcem_add_video(&v_plantronics);
	pcem_add_video(&v_virge375);
	pcem_add_video(&v_sigma400);
	pcem_add_video(&v_tvga8900d);
	pcem_add_video(&v_tvga9000b);
	pcem_add_video(&v_tgui9400cxi);
	pcem_add_video(&v_tgui9440);
	pcem_add_video(&v_tgkorvga);
	pcem_add_video(&v_et4000ax);
	pcem_add_video(&v_vga);
	pcem_add_video(&v_wy700);
}
