Files
86Box/src/video/video.c

1163 lines
44 KiB
C
Raw Normal View History

/*
2023-01-06 15:36:05 -05:00
* 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.
*
2023-01-06 15:36:05 -05:00
* This file is part of the 86Box distribution.
*
2023-01-06 15:36:05 -05:00
* Main video-rendering module.
*
2023-01-06 15:36:05 -05:00
* Video timing settings -
*
2023-01-06 15:36:05 -05:00
* 8-bit - 1mb/sec
* B = 8 ISA clocks
* W = 16 ISA clocks
* L = 32 ISA clocks
*
2023-01-06 15:36:05 -05:00
* Slow 16-bit - 2mb/sec
* B = 6 ISA clocks
* W = 8 ISA clocks
* L = 16 ISA clocks
*
2023-01-06 15:36:05 -05:00
* Fast 16-bit - 4mb/sec
* B = 3 ISA clocks
* W = 3 ISA clocks
* L = 6 ISA clocks
*
2023-01-06 15:36:05 -05:00
* Slow VLB/PCI - 8mb/sec (ish)
* B = 4 bus clocks
* W = 8 bus clocks
* L = 16 bus clocks
*
2023-01-06 15:36:05 -05:00
* Mid VLB/PCI -
* B = 4 bus clocks
* W = 5 bus clocks
* L = 10 bus clocks
*
2023-01-06 15:36:05 -05:00
* Fast VLB/PCI -
* B = 3 bus clocks
* W = 3 bus clocks
* L = 4 bus clocks
*
2020-03-25 00:46:02 +02:00
*
*
2023-01-06 15:36:29 -05:00
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
2023-01-06 15:36:05 -05:00
* Miran Grca, <mgrca8@gmail.com>
*
2023-01-06 15:36:05 -05:00
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
2022-07-04 17:54:38 +06:00
#include <stdatomic.h>
#define PNG_DEBUG 0
#include <png.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
2020-02-29 19:12:23 +01:00
#include "cpu.h"
#include <86box/device.h>
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/config.h>
#include <86box/timer.h>
2022-04-19 23:06:39 +02:00
#include <86box/path.h>
#include <86box/plat.h>
2022-07-04 01:50:42 +06:00
#include <86box/ui.h>
2022-04-19 23:06:39 +02:00
#include <86box/thread.h>
#include <86box/video.h>
#include <86box/vid_svga.h>
#include <minitrace/minitrace.h>
2022-08-31 19:19:29 -04:00
volatile int screenshots = 0;
uint8_t edatlookup[4][4];
uint8_t fontdat[2048][8]; /* IBM CGA font */
uint8_t fontdatm[2048][16]; /* IBM MDA font */
uint8_t fontdat2[2048][8]; /* IBM CGA 2nd instance font */
uint8_t fontdatm2[2048][16]; /* IBM MDA 2nd instance font */
2022-08-31 19:19:29 -04:00
uint8_t fontdatw[512][32]; /* Wyse700 font */
uint8_t fontdat8x12[256][16]; /* MDSI Genius font */
uint8_t fontdat12x18[256][36]; /* IM1024 font */
dbcs_font_t *fontdatksc5601 = NULL; /* Korean KSC-5601 font */
dbcs_font_t *fontdatksc5601_user = NULL; /* Korean KSC-5601 user defined font */
int herc_blend = 0;
int frames = 0;
int fullchange = 0;
int video_grayscale = 0;
int video_graytype = 0;
int monitor_index_global = 0;
2023-06-01 18:32:25 -04:00
uint32_t *video_6to8 = NULL;
uint32_t *video_8togs = NULL;
uint32_t *video_8to32 = NULL;
uint32_t *video_15to32 = NULL;
uint32_t *video_16to32 = NULL;
2022-08-31 19:19:29 -04:00
monitor_t monitors[MONITORS_NUM];
monitor_settings_t monitor_settings[MONITORS_NUM];
atomic_bool doresize_monitors[MONITORS_NUM];
#ifdef _WIN32
2022-08-31 19:19:29 -04:00
void *__cdecl (*video_copy)(void *_Dst, const void *_Src, size_t _Size) = memcpy;
#else
2022-08-31 19:19:29 -04:00
void *(*video_copy)(void *__restrict, const void *__restrict, size_t);
#endif
2023-08-11 20:32:56 -04:00
PALETTE cgapal = {
{0,0,0}, {0,42,0}, {42,0,0}, {42,21,0},
{0,0,0}, {0,42,42}, {42,0,42}, {42,42,42},
{0,0,0}, {21,63,21}, {63,21,21}, {63,63,21},
{0,0,0}, {21,63,63}, {63,21,63}, {63,63,63},
{0,0,0}, {0,0,42}, {0,42,0}, {0,42,42},
{42,0,0}, {42,0,42}, {42,21,00}, {42,42,42},
{21,21,21}, {21,21,63}, {21,63,21}, {21,63,63},
{63,21,21}, {63,21,63}, {63,63,21}, {63,63,63},
{0,0,0}, {0,21,0}, {0,0,42}, {0,42,42},
{42,0,21}, {21,10,21}, {42,0,42}, {42,0,63},
{21,21,21}, {21,63,21}, {42,21,42}, {21,63,63},
{63,0,0}, {42,42,0}, {63,21,42}, {41,41,41},
2022-02-20 02:26:27 -05:00
{0,0,0}, {0,42,42}, {42,0,0}, {42,42,42},
{0,0,0}, {0,42,42}, {42,0,0}, {42,42,42},
{0,0,0}, {0,63,63}, {63,0,0}, {63,63,63},
{0,0,0}, {0,63,63}, {63,0,0}, {63,63,63},
};
2023-08-11 20:32:56 -04:00
PALETTE cgapal_mono[6] = {
{ /* 0 - green, 4-color-optimized contrast. */
{0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x17,0x05},
{0x01,0x1a,0x06},{0x02,0x28,0x09},{0x02,0x2c,0x0a},
{0x03,0x39,0x0d},{0x03,0x3c,0x0e},{0x00,0x07,0x01},
{0x01,0x13,0x04},{0x01,0x1f,0x07},{0x01,0x23,0x08},
{0x02,0x31,0x0b},{0x02,0x35,0x0c},{0x05,0x3f,0x11},{0x0d,0x3f,0x17},
},
2023-08-11 20:32:56 -04:00
{ /* 1 - green, 16-color-optimized contrast. */
{0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x15,0x05},
{0x01,0x17,0x05},{0x01,0x21,0x08},{0x01,0x24,0x08},
{0x02,0x2e,0x0b},{0x02,0x31,0x0b},{0x01,0x22,0x08},
{0x02,0x28,0x09},{0x02,0x30,0x0b},{0x02,0x32,0x0c},
{0x03,0x39,0x0d},{0x03,0x3b,0x0e},{0x09,0x3f,0x14},{0x0d,0x3f,0x17},
},
2023-08-11 20:32:56 -04:00
{ /* 2 - amber, 4-color-optimized contrast. */
{0x00,0x00,0x00},{0x15,0x05,0x00},{0x20,0x0b,0x00},
{0x24,0x0d,0x00},{0x33,0x18,0x00},{0x37,0x1b,0x00},
{0x3f,0x26,0x01},{0x3f,0x2b,0x06},{0x0b,0x02,0x00},
{0x1b,0x08,0x00},{0x29,0x11,0x00},{0x2e,0x14,0x00},
{0x3b,0x1e,0x00},{0x3e,0x21,0x00},{0x3f,0x32,0x0a},{0x3f,0x38,0x0d},
},
2023-08-11 20:32:56 -04:00
{ /* 3 - amber, 16-color-optimized contrast. */
{0x00,0x00,0x00},{0x15,0x05,0x00},{0x1e,0x09,0x00},
{0x21,0x0b,0x00},{0x2b,0x12,0x00},{0x2f,0x15,0x00},
{0x38,0x1c,0x00},{0x3b,0x1e,0x00},{0x2c,0x13,0x00},
{0x32,0x17,0x00},{0x3a,0x1e,0x00},{0x3c,0x1f,0x00},
{0x3f,0x27,0x01},{0x3f,0x2a,0x04},{0x3f,0x36,0x0c},{0x3f,0x38,0x0d},
},
2023-08-11 20:32:56 -04:00
{ /* 4 - grey, 4-color-optimized contrast. */
{0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x15,0x17,0x18},
{0x18,0x1a,0x1b},{0x24,0x25,0x25},{0x27,0x28,0x28},
{0x33,0x34,0x32},{0x37,0x38,0x35},{0x09,0x0a,0x0b},
{0x11,0x12,0x13},{0x1c,0x1e,0x1e},{0x20,0x22,0x22},
{0x2c,0x2d,0x2c},{0x2f,0x30,0x2f},{0x3c,0x3c,0x38},{0x3f,0x3f,0x3b},
},
2023-08-11 20:32:56 -04:00
{ /* 5 - grey, 16-color-optimized contrast. */
{0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x13,0x14,0x15},
{0x15,0x17,0x18},{0x1e,0x20,0x20},{0x20,0x22,0x22},
{0x29,0x2a,0x2a},{0x2c,0x2d,0x2c},{0x1f,0x21,0x21},
{0x23,0x25,0x25},{0x2b,0x2c,0x2b},{0x2d,0x2e,0x2d},
{0x34,0x35,0x33},{0x37,0x37,0x34},{0x3e,0x3e,0x3a},{0x3f,0x3f,0x3b},
}
};
2023-08-11 20:32:56 -04:00
const uint32_t shade[5][256] = {
{0}, // RGB Color (unused)
{0}, // RGB Grayscale (unused)
{ // Amber monitor
0x000000, 0x060000, 0x090000, 0x0d0000, 0x100000, 0x120100, 0x150100, 0x170100, 0x1a0100, 0x1c0100, 0x1e0200, 0x210200, 0x230200, 0x250300, 0x270300, 0x290300,
0x2b0400, 0x2d0400, 0x2f0400, 0x300500, 0x320500, 0x340500, 0x360600, 0x380600, 0x390700, 0x3b0700, 0x3d0700, 0x3f0800, 0x400800, 0x420900, 0x440900, 0x450a00,
0x470a00, 0x480b00, 0x4a0b00, 0x4c0c00, 0x4d0c00, 0x4f0d00, 0x500d00, 0x520e00, 0x530e00, 0x550f00, 0x560f00, 0x581000, 0x591000, 0x5b1100, 0x5c1200, 0x5e1200,
0x5f1300, 0x601300, 0x621400, 0x631500, 0x651500, 0x661600, 0x671600, 0x691700, 0x6a1800, 0x6c1800, 0x6d1900, 0x6e1a00, 0x701a00, 0x711b00, 0x721c00, 0x741c00,
0x751d00, 0x761e00, 0x781e00, 0x791f00, 0x7a2000, 0x7c2000, 0x7d2100, 0x7e2200, 0x7f2300, 0x812300, 0x822400, 0x832500, 0x842600, 0x862600, 0x872700, 0x882800,
0x8a2900, 0x8b2900, 0x8c2a00, 0x8d2b00, 0x8e2c00, 0x902c00, 0x912d00, 0x922e00, 0x932f00, 0x953000, 0x963000, 0x973100, 0x983200, 0x993300, 0x9b3400, 0x9c3400,
0x9d3500, 0x9e3600, 0x9f3700, 0xa03800, 0xa23900, 0xa33a00, 0xa43a00, 0xa53b00, 0xa63c00, 0xa73d00, 0xa93e00, 0xaa3f00, 0xab4000, 0xac4000, 0xad4100, 0xae4200,
0xaf4300, 0xb14400, 0xb24500, 0xb34600, 0xb44700, 0xb54800, 0xb64900, 0xb74a00, 0xb94a00, 0xba4b00, 0xbb4c00, 0xbc4d00, 0xbd4e00, 0xbe4f00, 0xbf5000, 0xc05100,
0xc15200, 0xc25300, 0xc45400, 0xc55500, 0xc65600, 0xc75700, 0xc85800, 0xc95900, 0xca5a00, 0xcb5b00, 0xcc5c00, 0xcd5d00, 0xce5e00, 0xcf5f00, 0xd06000, 0xd26101,
0xd36201, 0xd46301, 0xd56401, 0xd66501, 0xd76601, 0xd86701, 0xd96801, 0xda6901, 0xdb6a01, 0xdc6b01, 0xdd6c01, 0xde6d01, 0xdf6e01, 0xe06f01, 0xe17001, 0xe27201,
0xe37301, 0xe47401, 0xe57501, 0xe67602, 0xe77702, 0xe87802, 0xe97902, 0xeb7a02, 0xec7b02, 0xed7c02, 0xee7e02, 0xef7f02, 0xf08002, 0xf18103, 0xf28203, 0xf38303,
0xf48403, 0xf58503, 0xf68703, 0xf78803, 0xf88903, 0xf98a04, 0xfa8b04, 0xfb8c04, 0xfc8d04, 0xfd8f04, 0xfe9005, 0xff9105, 0xff9205, 0xff9305, 0xff9405, 0xff9606,
0xff9706, 0xff9806, 0xff9906, 0xff9a07, 0xff9b07, 0xff9d07, 0xff9e08, 0xff9f08, 0xffa008, 0xffa109, 0xffa309, 0xffa409, 0xffa50a, 0xffa60a, 0xffa80a, 0xffa90b,
0xffaa0b, 0xffab0c, 0xffac0c, 0xffae0d, 0xffaf0d, 0xffb00e, 0xffb10e, 0xffb30f, 0xffb40f, 0xffb510, 0xffb610, 0xffb811, 0xffb912, 0xffba12, 0xffbb13, 0xffbd14,
0xffbe14, 0xffbf15, 0xffc016, 0xffc217, 0xffc317, 0xffc418, 0xffc619, 0xffc71a, 0xffc81b, 0xffca1c, 0xffcb1d, 0xffcc1e, 0xffcd1f, 0xffcf20, 0xffd021, 0xffd122,
0xffd323, 0xffd424, 0xffd526, 0xffd727, 0xffd828, 0xffd92a, 0xffdb2b, 0xffdc2c, 0xffdd2e, 0xffdf2f, 0xffe031, 0xffe133, 0xffe334, 0xffe436, 0xffe538, 0xffe739
},
{ // Green monitor
0x000000, 0x000400, 0x000700, 0x000900, 0x000b00, 0x000d00, 0x000f00, 0x001100, 0x001300, 0x001500, 0x001600, 0x001800, 0x001a00, 0x001b00, 0x001d00, 0x001e00,
0x002000, 0x002100, 0x002300, 0x002400, 0x002601, 0x002701, 0x002901, 0x002a01, 0x002b01, 0x002d01, 0x002e01, 0x002f01, 0x003101, 0x003201, 0x003301, 0x003401,
0x003601, 0x003702, 0x003802, 0x003902, 0x003b02, 0x003c02, 0x003d02, 0x003e02, 0x004002, 0x004102, 0x004203, 0x004303, 0x004403, 0x004503, 0x004703, 0x004803,
0x004903, 0x004a03, 0x004b04, 0x004c04, 0x004d04, 0x004e04, 0x005004, 0x005104, 0x005205, 0x005305, 0x005405, 0x005505, 0x005605, 0x005705, 0x005806, 0x005906,
0x005a06, 0x005b06, 0x005d06, 0x005e07, 0x005f07, 0x006007, 0x006107, 0x006207, 0x006308, 0x006408, 0x006508, 0x006608, 0x006708, 0x006809, 0x006909, 0x006a09,
0x006b09, 0x016c0a, 0x016d0a, 0x016e0a, 0x016f0a, 0x01700b, 0x01710b, 0x01720b, 0x01730b, 0x01740c, 0x01750c, 0x01760c, 0x01770c, 0x01780d, 0x01790d, 0x017a0d,
0x017b0d, 0x017b0e, 0x017c0e, 0x017d0e, 0x017e0f, 0x017f0f, 0x01800f, 0x018110, 0x028210, 0x028310, 0x028410, 0x028511, 0x028611, 0x028711, 0x028812, 0x028912,
0x028a12, 0x028a13, 0x028b13, 0x028c13, 0x028d14, 0x028e14, 0x038f14, 0x039015, 0x039115, 0x039215, 0x039316, 0x039416, 0x039417, 0x039517, 0x039617, 0x039718,
0x049818, 0x049918, 0x049a19, 0x049b19, 0x049c19, 0x049c1a, 0x049d1a, 0x049e1b, 0x059f1b, 0x05a01b, 0x05a11c, 0x05a21c, 0x05a31c, 0x05a31d, 0x05a41d, 0x06a51e,
0x06a61e, 0x06a71f, 0x06a81f, 0x06a920, 0x06aa20, 0x07aa21, 0x07ab21, 0x07ac21, 0x07ad22, 0x07ae22, 0x08af23, 0x08b023, 0x08b024, 0x08b124, 0x08b225, 0x09b325,
0x09b426, 0x09b526, 0x09b527, 0x0ab627, 0x0ab728, 0x0ab828, 0x0ab929, 0x0bba29, 0x0bba2a, 0x0bbb2a, 0x0bbc2b, 0x0cbd2b, 0x0cbe2c, 0x0cbf2c, 0x0dbf2d, 0x0dc02d,
0x0dc12e, 0x0ec22e, 0x0ec32f, 0x0ec42f, 0x0fc430, 0x0fc530, 0x0fc631, 0x10c731, 0x10c832, 0x10c932, 0x11c933, 0x11ca33, 0x11cb34, 0x12cc35, 0x12cd35, 0x12cd36,
0x13ce36, 0x13cf37, 0x13d037, 0x14d138, 0x14d139, 0x14d239, 0x15d33a, 0x15d43a, 0x16d43b, 0x16d53b, 0x17d63c, 0x17d73d, 0x17d83d, 0x18d83e, 0x18d93e, 0x19da3f,
0x19db40, 0x1adc40, 0x1adc41, 0x1bdd41, 0x1bde42, 0x1cdf43, 0x1ce043, 0x1de044, 0x1ee145, 0x1ee245, 0x1fe346, 0x1fe446, 0x20e447, 0x20e548, 0x21e648, 0x22e749,
0x22e74a, 0x23e84a, 0x23e94b, 0x24ea4c, 0x25ea4c, 0x25eb4d, 0x26ec4e, 0x27ed4e, 0x27ee4f, 0x28ee50, 0x29ef50, 0x29f051, 0x2af152, 0x2bf153, 0x2cf253, 0x2cf354,
0x2df455, 0x2ef455, 0x2ff556, 0x2ff657, 0x30f758, 0x31f758, 0x32f859, 0x32f95a, 0x33fa5a, 0x34fa5b, 0x35fb5c, 0x36fc5d, 0x37fd5d, 0x38fd5e, 0x38fe5f, 0x39ff60
},
{ // White monitor
0x000000, 0x010102, 0x020203, 0x020304, 0x030406, 0x040507, 0x050608, 0x060709, 0x07080a, 0x08090c, 0x080a0d, 0x090b0e, 0x0a0c0f, 0x0b0d10, 0x0c0e11, 0x0d0f12,
0x0e1013, 0x0f1115, 0x101216, 0x111317, 0x121418, 0x121519, 0x13161a, 0x14171b, 0x15181c, 0x16191d, 0x171a1e, 0x181b1f, 0x191c20, 0x1a1d21, 0x1b1e22, 0x1c1f23,
0x1d2024, 0x1e2125, 0x1f2226, 0x202327, 0x212428, 0x222529, 0x22262b, 0x23272c, 0x24282d, 0x25292e, 0x262a2f, 0x272b30, 0x282c30, 0x292d31, 0x2a2e32, 0x2b2f33,
0x2c3034, 0x2d3035, 0x2e3136, 0x2f3237, 0x303338, 0x313439, 0x32353a, 0x33363b, 0x34373c, 0x35383d, 0x36393e, 0x373a3f, 0x383b40, 0x393c41, 0x3a3d42, 0x3b3e43,
0x3c3f44, 0x3d4045, 0x3e4146, 0x3f4247, 0x404348, 0x414449, 0x42454a, 0x43464b, 0x44474c, 0x45484d, 0x46494d, 0x474a4e, 0x484b4f, 0x484c50, 0x494d51, 0x4a4e52,
0x4b4f53, 0x4c5054, 0x4d5155, 0x4e5256, 0x4f5357, 0x505458, 0x515559, 0x52565a, 0x53575b, 0x54585b, 0x55595c, 0x565a5d, 0x575b5e, 0x585c5f, 0x595d60, 0x5a5e61,
0x5b5f62, 0x5c6063, 0x5d6164, 0x5e6265, 0x5f6366, 0x606466, 0x616567, 0x626668, 0x636769, 0x64686a, 0x65696b, 0x666a6c, 0x676b6d, 0x686c6e, 0x696d6f, 0x6a6e70,
0x6b6f70, 0x6c7071, 0x6d7172, 0x6f7273, 0x707374, 0x707475, 0x717576, 0x727677, 0x747778, 0x757879, 0x767979, 0x777a7a, 0x787b7b, 0x797c7c, 0x7a7d7d, 0x7b7e7e,
0x7c7f7f, 0x7d8080, 0x7e8181, 0x7f8281, 0x808382, 0x818483, 0x828584, 0x838685, 0x848786, 0x858887, 0x868988, 0x878a89, 0x888b89, 0x898c8a, 0x8a8d8b, 0x8b8e8c,
0x8c8f8d, 0x8d8f8e, 0x8e908f, 0x8f9190, 0x909290, 0x919391, 0x929492, 0x939593, 0x949694, 0x959795, 0x969896, 0x979997, 0x989a98, 0x999b98, 0x9a9c99, 0x9b9d9a,
0x9c9e9b, 0x9d9f9c, 0x9ea09d, 0x9fa19e, 0xa0a29f, 0xa1a39f, 0xa2a4a0, 0xa3a5a1, 0xa4a6a2, 0xa6a7a3, 0xa7a8a4, 0xa8a9a5, 0xa9aaa5, 0xaaaba6, 0xabaca7, 0xacada8,
0xadaea9, 0xaeafaa, 0xafb0ab, 0xb0b1ac, 0xb1b2ac, 0xb2b3ad, 0xb3b4ae, 0xb4b5af, 0xb5b6b0, 0xb6b7b1, 0xb7b8b2, 0xb8b9b2, 0xb9bab3, 0xbabbb4, 0xbbbcb5, 0xbcbdb6,
0xbdbeb7, 0xbebfb8, 0xbfc0b8, 0xc0c1b9, 0xc1c2ba, 0xc2c3bb, 0xc3c4bc, 0xc5c5bd, 0xc6c6be, 0xc7c7be, 0xc8c8bf, 0xc9c9c0, 0xcacac1, 0xcbcbc2, 0xccccc3, 0xcdcdc3,
0xcecec4, 0xcfcfc5, 0xd0d0c6, 0xd1d1c7, 0xd2d2c8, 0xd3d3c9, 0xd4d4c9, 0xd5d5ca, 0xd6d6cb, 0xd7d7cc, 0xd8d8cd, 0xd9d9ce, 0xdadacf, 0xdbdbcf, 0xdcdcd0, 0xdeddd1,
0xdfded2, 0xe0dfd3, 0xe1e0d4, 0xe2e1d4, 0xe3e2d5, 0xe4e3d6, 0xe5e4d7, 0xe6e5d8, 0xe7e6d9, 0xe8e7d9, 0xe9e8da, 0xeae9db, 0xebeadc, 0xecebdd, 0xedecde, 0xeeeddf,
0xefeedf, 0xf0efe0, 0xf1f0e1, 0xf2f1e2, 0xf3f2e3, 0xf4f3e3, 0xf6f3e4, 0xf7f4e5, 0xf8f5e6, 0xf9f6e7, 0xfaf7e8, 0xfbf8e9, 0xfcf9e9, 0xfdfaea, 0xfefbeb, 0xfffcec
}
};
typedef struct blit_data_struct {
2022-08-31 19:19:29 -04:00
int x, y, w, h;
int busy;
int buffer_in_use;
int thread_run;
int monitor_index;
thread_t *blit_thread;
event_t *wake_blit_thread;
event_t *blit_complete;
event_t *buffer_not_in_use;
} blit_data_t;
2022-08-31 19:19:29 -04:00
static uint32_t cga_2_table[16];
static void (*blit_func)(int x, int y, int w, int h, int monitor_index);
#ifdef ENABLE_VIDEO_LOG
int video_do_log = ENABLE_VIDEO_LOG;
static void
video_log(const char *fmt, ...)
{
va_list ap;
if (video_do_log) {
2022-08-31 19:19:29 -04:00
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
2022-08-31 19:19:29 -04:00
# define video_log(fmt, ...)
#endif
void
2022-08-31 19:19:29 -04:00
video_setblit(void (*blit)(int, int, int, int, int))
{
blit_func = blit;
}
void
video_blit_complete_monitor(int monitor_index)
{
2022-08-31 19:19:29 -04:00
blit_data_t *blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr;
blit_data_ptr->buffer_in_use = 0;
thread_set_event(blit_data_ptr->buffer_not_in_use);
}
void
video_wait_for_blit_monitor(int monitor_index)
{
2022-08-31 19:19:29 -04:00
blit_data_t *blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr;
while (blit_data_ptr->busy)
2022-08-31 19:19:29 -04:00
thread_wait_event(blit_data_ptr->blit_complete, -1);
thread_reset_event(blit_data_ptr->blit_complete);
}
void
video_wait_for_buffer_monitor(int monitor_index)
{
2022-08-31 19:19:29 -04:00
blit_data_t *blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr;
while (blit_data_ptr->buffer_in_use)
2022-08-31 19:19:29 -04:00
thread_wait_event(blit_data_ptr->buffer_not_in_use, -1);
thread_reset_event(blit_data_ptr->buffer_not_in_use);
}
2022-08-31 19:19:29 -04:00
static png_structp png_ptr[MONITORS_NUM];
static png_infop info_ptr[MONITORS_NUM];
static void
video_take_screenshot_monitor(const char *fn, uint32_t *buf, int start_x, int start_y, int row_len, int monitor_index)
{
2023-07-31 17:31:15 -04:00
png_bytep *b_rgb = NULL;
FILE *fp = NULL;
uint32_t temp = 0x00000000;
const blit_data_t *blit_data_ptr = monitors[monitor_index].mon_blit_data_ptr;
/* create file */
2023-07-31 17:31:15 -04:00
fp = plat_fopen(fn, (const char *) "wb");
if (!fp) {
2022-08-31 19:19:29 -04:00
video_log("[video_take_screenshot] File %s could not be opened for writing", fn);
return;
}
/* initialize stuff */
png_ptr[monitor_index] = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr[monitor_index]) {
2022-08-31 19:19:29 -04:00
video_log("[video_take_screenshot] png_create_write_struct failed");
fclose(fp);
return;
}
info_ptr[monitor_index] = png_create_info_struct(png_ptr[monitor_index]);
if (!info_ptr[monitor_index]) {
2022-08-31 19:19:29 -04:00
video_log("[video_take_screenshot] png_create_info_struct failed");
fclose(fp);
return;
}
png_init_io(png_ptr[monitor_index], fp);
png_set_IHDR(png_ptr[monitor_index], info_ptr[monitor_index], blit_data_ptr->w, blit_data_ptr->h,
2022-08-31 19:19:29 -04:00
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * blit_data_ptr->h);
if (b_rgb == NULL) {
2022-08-31 19:19:29 -04:00
video_log("[video_take_screenshot] Unable to Allocate RGB Bitmap Memory");
fclose(fp);
return;
}
2023-06-01 18:32:25 -04:00
for (int y = 0; y < blit_data_ptr->h; ++y) {
2022-08-31 19:19:29 -04:00
b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr[monitor_index], info_ptr[monitor_index]));
2023-06-01 18:32:25 -04:00
for (int x = 0; x < blit_data_ptr->w; ++x) {
2022-08-31 19:19:29 -04:00
if (buf == NULL)
memset(&(b_rgb[y][x * 3]), 0x00, 3);
else {
temp = buf[((start_y + y) * row_len) + start_x + x];
b_rgb[y][x * 3] = (temp >> 16) & 0xff;
b_rgb[y][(x * 3) + 1] = (temp >> 8) & 0xff;
b_rgb[y][(x * 3) + 2] = temp & 0xff;
}
}
}
png_write_info(png_ptr[monitor_index], info_ptr[monitor_index]);
png_write_image(png_ptr[monitor_index], b_rgb);
png_write_end(png_ptr[monitor_index], NULL);
/* cleanup heap allocation */
2023-06-01 18:32:25 -04:00
for (int i = 0; i < blit_data_ptr->h; i++)
2022-08-31 19:19:29 -04:00
if (b_rgb[i])
free(b_rgb[i]);
2022-08-31 19:19:29 -04:00
if (b_rgb)
free(b_rgb);
2022-08-31 19:19:29 -04:00
if (fp)
fclose(fp);
}
void
video_screenshot_monitor(uint32_t *buf, int start_x, int start_y, int row_len, int monitor_index)
{
2023-06-01 18:32:25 -04:00
char path[1024];
char fn[256];
memset(fn, 0, sizeof(fn));
memset(path, 0, sizeof(path));
2022-04-19 23:06:39 +02:00
path_append_filename(path, usr_path, SCREENSHOT_PATH);
2022-08-31 19:19:29 -04:00
if (!plat_dir_check(path))
plat_dir_create(path);
2022-04-19 23:06:39 +02:00
path_slash(path);
2022-07-07 16:09:50 +06:00
strcat(path, "Monitor_");
snprintf(&path[strlen(path)], 42, "%d_", monitor_index + 1);
plat_tempfile(fn, NULL, ".png");
strcat(path, fn);
video_log("taking screenshot to: %s\n", path);
video_take_screenshot_monitor((const char *) path, buf, start_x, start_y, row_len, monitor_index);
png_destroy_write_struct(&png_ptr[monitor_index], &info_ptr[monitor_index]);
2022-07-11 21:34:58 +06:00
atomic_fetch_sub(&monitors[monitor_index].mon_screenshots, 1);
}
void
video_screenshot(uint32_t *buf, int start_x, int start_y, int row_len)
{
2022-07-07 16:09:50 +06:00
video_screenshot_monitor(buf, start_x, start_y, row_len, 0);
}
#ifdef _WIN32
2022-08-31 19:19:29 -04:00
void *__cdecl video_transform_copy(void *_Dst, const void *_Src, size_t _Size)
#else
void *
video_transform_copy(void *__restrict _Dst, const void *__restrict _Src, size_t _Size)
#endif
{
2023-07-31 17:31:15 -04:00
uint32_t *dest_ex = (uint32_t *) _Dst;
const uint32_t *src_ex = (const uint32_t *) _Src;
_Size /= sizeof(uint32_t);
if ((dest_ex != NULL) && (src_ex != NULL)) {
2023-06-01 18:32:25 -04:00
for (size_t i = 0; i < _Size; i++) {
2022-08-31 19:19:29 -04:00
*dest_ex = video_color_transform(*src_ex);
dest_ex++;
src_ex++;
}
}
return _Dst;
}
2022-08-31 19:19:29 -04:00
static void
blit_thread(void *param)
{
2022-08-31 19:19:29 -04:00
blit_data_t *data = param;
while (data->thread_run) {
2022-08-31 19:19:29 -04:00
thread_wait_event(data->wake_blit_thread, -1);
thread_reset_event(data->wake_blit_thread);
MTR_BEGIN("video", "blit_thread");
2022-08-31 19:19:29 -04:00
if (blit_func)
blit_func(data->x, data->y, data->w, data->h, data->monitor_index);
2022-08-31 19:19:29 -04:00
data->busy = 0;
2022-08-31 19:19:29 -04:00
MTR_END("video", "blit_thread");
thread_set_event(data->blit_complete);
}
}
void
video_blit_memtoscreen_monitor(int x, int y, int w, int h, int monitor_index)
{
MTR_BEGIN("video", "video_blit_memtoscreen");
if ((w <= 0) || (h <= 0))
2022-08-31 19:19:29 -04:00
return;
video_wait_for_blit_monitor(monitor_index);
2022-08-31 19:19:29 -04:00
monitors[monitor_index].mon_blit_data_ptr->busy = 1;
monitors[monitor_index].mon_blit_data_ptr->buffer_in_use = 1;
2022-08-31 19:19:29 -04:00
monitors[monitor_index].mon_blit_data_ptr->x = x;
monitors[monitor_index].mon_blit_data_ptr->y = y;
monitors[monitor_index].mon_blit_data_ptr->w = w;
monitors[monitor_index].mon_blit_data_ptr->h = h;
thread_set_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread);
MTR_END("video", "video_blit_memtoscreen");
}
2022-08-31 19:19:29 -04:00
uint8_t
pixels8(uint32_t *pixels)
{
uint8_t temp = 0;
2023-06-01 18:32:25 -04:00
for (uint8_t i = 0; i < 8; i++)
2022-08-31 19:19:29 -04:00
temp |= (!!*(pixels + i) << (i ^ 7));
return temp;
}
2022-08-31 19:19:29 -04:00
uint32_t
pixel_to_color(uint8_t *pixels32, uint8_t pos)
{
uint32_t temp;
temp = *(pixels32 + pos) & 0x03;
switch (temp) {
2022-08-31 19:19:29 -04:00
default:
2023-07-31 17:31:15 -04:00
case 0:
2022-08-31 19:19:29 -04:00
return 0x00;
case 1:
return 0x07;
case 2:
return 0x0f;
}
}
void
video_blend_monitor(int x, int y, int monitor_index)
{
2023-06-01 18:32:25 -04:00
uint32_t pixels32_1;
uint32_t pixels32_2;
unsigned int val1;
unsigned int val2;
static unsigned int carry = 0;
if (!herc_blend)
2022-08-31 19:19:29 -04:00
return;
if (!x)
2022-08-31 19:19:29 -04:00
carry = 0;
2022-08-31 19:19:29 -04:00
val1 = pixels8(&(monitors[monitor_index].target_buffer->line[y][x]));
val2 = (val1 >> 1) + carry;
carry = (val1 & 1) << 7;
pixels32_1 = cga_2_table[val1 >> 4] + cga_2_table[val2 >> 4];
pixels32_2 = cga_2_table[val1 & 0xf] + cga_2_table[val2 & 0xf];
2023-06-01 18:32:25 -04:00
for (uint8_t xx = 0; xx < 4; xx++) {
2022-08-31 19:19:29 -04:00
monitors[monitor_index].target_buffer->line[y][x + xx] = pixel_to_color((uint8_t *) &pixels32_1, xx);
monitors[monitor_index].target_buffer->line[y][x + (xx | 4)] = pixel_to_color((uint8_t *) &pixels32_2, xx);
}
}
void
video_process_8_monitor(int x, int y, int monitor_index)
{
2023-06-01 18:32:25 -04:00
for (int xx = 0; xx < x; xx++) {
if (monitors[monitor_index].target_buffer->line[y][xx] <= 0xff)
monitors[monitor_index].target_buffer->line[y][xx] = monitors[monitor_index].mon_pal_lookup[monitors[monitor_index].target_buffer->line[y][xx]];
else
2022-11-19 08:49:04 -05:00
monitors[monitor_index].target_buffer->line[y][xx] = 0x00000000;
}
}
void
cgapal_rebuild_monitor(int monitor_index)
{
2022-08-31 19:19:29 -04:00
int c;
uint32_t *palette_lookup = monitors[monitor_index].mon_pal_lookup;
int cga_palette_monitor = 0;
/* We cannot do this (yet) if we have not been enabled yet. */
2022-08-31 19:19:29 -04:00
if (video_6to8 == NULL)
return;
2022-08-31 19:19:29 -04:00
if (monitors[monitor_index].target_buffer == NULL || monitors[monitor_index].mon_cga_palette == NULL)
return;
2022-07-07 14:34:59 +06:00
cga_palette_monitor = *monitors[monitor_index].mon_cga_palette;
2022-08-31 19:19:29 -04:00
for (c = 0; c < 256; c++) {
palette_lookup[c] = makecol(video_6to8[cgapal[c].r],
video_6to8[cgapal[c].g],
video_6to8[cgapal[c].b]);
}
if ((cga_palette_monitor > 1) && (cga_palette_monitor < 7)) {
2022-08-31 19:19:29 -04:00
if (vid_cga_contrast != 0) {
for (c = 0; c < 16; c++) {
palette_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]);
palette_lookup[c + 16] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]);
palette_lookup[c + 32] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]);
palette_lookup[c + 48] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 2][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 2][c].b]);
}
} else {
for (c = 0; c < 16; c++) {
palette_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]);
palette_lookup[c + 16] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]);
palette_lookup[c + 32] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]);
palette_lookup[c + 48] = makecol(video_6to8[cgapal_mono[cga_palette_monitor - 1][c].r],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].g],
video_6to8[cgapal_mono[cga_palette_monitor - 1][c].b]);
}
}
}
if (cga_palette_monitor == 7)
2022-08-31 19:19:29 -04:00
palette_lookup[0x16] = makecol(video_6to8[42], video_6to8[42], video_6to8[0]);
}
void
video_inform_monitor(int type, const video_timings_t *ptr, int monitor_index)
{
2022-08-31 19:19:29 -04:00
monitor_t *monitor = &monitors[monitor_index];
monitor->mon_vid_type = type;
monitor->mon_vid_timings = ptr;
}
int
video_get_type_monitor(int monitor_index)
{
return monitors[monitor_index].mon_vid_type;
}
void
video_update_timing(void)
{
2022-08-31 19:19:29 -04:00
const video_timings_t *monitor_vid_timings = NULL;
int *vid_timing_read_b = NULL;
int *vid_timing_read_l = NULL;
int *vid_timing_read_w = NULL;
int *vid_timing_write_b = NULL;
int *vid_timing_write_l = NULL;
int *vid_timing_write_w = NULL;
2023-06-01 18:32:25 -04:00
for (uint8_t i = 0; i < MONITORS_NUM; i++) {
monitor_vid_timings = monitors[i].mon_vid_timings;
if (!monitor_vid_timings)
2022-08-31 19:19:29 -04:00
continue;
vid_timing_read_b = &monitors[i].mon_video_timing_read_b;
vid_timing_read_l = &monitors[i].mon_video_timing_read_l;
vid_timing_read_w = &monitors[i].mon_video_timing_read_w;
vid_timing_write_b = &monitors[i].mon_video_timing_write_b;
vid_timing_write_l = &monitors[i].mon_video_timing_write_l;
vid_timing_write_w = &monitors[i].mon_video_timing_write_w;
if (monitor_vid_timings->type == VIDEO_ISA) {
2022-08-31 19:19:29 -04:00
*vid_timing_read_b = ISA_CYCLES(monitor_vid_timings->read_b);
*vid_timing_read_w = ISA_CYCLES(monitor_vid_timings->read_w);
*vid_timing_read_l = ISA_CYCLES(monitor_vid_timings->read_l);
*vid_timing_write_b = ISA_CYCLES(monitor_vid_timings->write_b);
*vid_timing_write_w = ISA_CYCLES(monitor_vid_timings->write_w);
*vid_timing_write_l = ISA_CYCLES(monitor_vid_timings->write_l);
2022-07-07 14:34:59 +06:00
} else if (monitor_vid_timings->type == VIDEO_PCI) {
2022-08-31 19:19:29 -04:00
*vid_timing_read_b = (int) (pci_timing * monitor_vid_timings->read_b);
*vid_timing_read_w = (int) (pci_timing * monitor_vid_timings->read_w);
*vid_timing_read_l = (int) (pci_timing * monitor_vid_timings->read_l);
*vid_timing_write_b = (int) (pci_timing * monitor_vid_timings->write_b);
*vid_timing_write_w = (int) (pci_timing * monitor_vid_timings->write_w);
*vid_timing_write_l = (int) (pci_timing * monitor_vid_timings->write_l);
2022-07-07 14:34:59 +06:00
} else if (monitor_vid_timings->type == VIDEO_AGP) {
2022-08-31 19:19:29 -04:00
*vid_timing_read_b = (int) (agp_timing * monitor_vid_timings->read_b);
*vid_timing_read_w = (int) (agp_timing * monitor_vid_timings->read_w);
*vid_timing_read_l = (int) (agp_timing * monitor_vid_timings->read_l);
*vid_timing_write_b = (int) (agp_timing * monitor_vid_timings->write_b);
*vid_timing_write_w = (int) (agp_timing * monitor_vid_timings->write_w);
*vid_timing_write_l = (int) (agp_timing * monitor_vid_timings->write_l);
} else {
2022-08-31 19:19:29 -04:00
*vid_timing_read_b = (int) (bus_timing * monitor_vid_timings->read_b);
*vid_timing_read_w = (int) (bus_timing * monitor_vid_timings->read_w);
*vid_timing_read_l = (int) (bus_timing * monitor_vid_timings->read_l);
*vid_timing_write_b = (int) (bus_timing * monitor_vid_timings->write_b);
*vid_timing_write_w = (int) (bus_timing * monitor_vid_timings->write_w);
*vid_timing_write_l = (int) (bus_timing * monitor_vid_timings->write_l);
}
if (cpu_16bitbus) {
2022-08-31 19:19:29 -04:00
*vid_timing_read_l = *vid_timing_read_w * 2;
*vid_timing_write_l = *vid_timing_write_w * 2;
}
}
}
int
calc_6to8(int c)
{
2023-06-01 18:32:25 -04:00
int ic;
int i8;
double d8;
ic = c;
if (ic == 64)
2022-08-31 19:19:29 -04:00
ic = 63;
else
ic &= 0x3f;
d8 = (ic / 63.0) * 255.0;
i8 = (int) d8;
2022-08-31 19:19:29 -04:00
return (i8 & 0xff);
}
int
calc_8to32(int c)
{
2023-06-01 18:32:25 -04:00
int b;
int g;
int r;
double db;
double dg;
double dr;
2022-08-31 19:19:29 -04:00
b = (c & 3);
g = ((c >> 2) & 7);
r = ((c >> 5) & 7);
db = (((double) b) / 3.0) * 255.0;
dg = (((double) g) / 7.0) * 255.0;
dr = (((double) r) / 7.0) * 255.0;
b = (int) db;
g = ((int) dg) << 8;
r = ((int) dr) << 16;
return (b | g | r);
}
int
calc_15to32(int c)
{
2023-06-01 18:32:25 -04:00
int b;
int g;
int r;
double db;
double dg;
double dr;
2022-08-31 19:19:29 -04:00
b = (c & 31);
g = ((c >> 5) & 31);
r = ((c >> 10) & 31);
db = (((double) b) / 31.0) * 255.0;
dg = (((double) g) / 31.0) * 255.0;
dr = (((double) r) / 31.0) * 255.0;
2022-08-31 19:19:29 -04:00
b = (int) db;
g = ((int) dg) << 8;
r = ((int) dr) << 16;
2022-08-31 19:19:29 -04:00
return (b | g | r);
}
int
calc_16to32(int c)
{
2023-06-01 18:32:25 -04:00
int b;
int g;
int r;
double db;
double dg;
double dr;
2022-08-31 19:19:29 -04:00
b = (c & 31);
g = ((c >> 5) & 63);
r = ((c >> 11) & 31);
db = (((double) b) / 31.0) * 255.0;
dg = (((double) g) / 63.0) * 255.0;
dr = (((double) r) / 31.0) * 255.0;
2022-08-31 19:19:29 -04:00
b = (int) db;
g = ((int) dg) << 8;
r = ((int) dr) << 16;
2022-08-31 19:19:29 -04:00
return (b | g | r);
}
void
hline(bitmap_t *b, int x1, int y, int x2, uint32_t col)
{
if (y < 0 || y >= b->h)
2022-08-31 19:19:29 -04:00
return;
2023-06-01 18:32:25 -04:00
for (int x = x1; x < x2; x++)
2022-08-31 19:19:29 -04:00
b->line[y][x] = col;
}
void
2023-07-31 17:31:15 -04:00
blit(UNUSED(bitmap_t *src), UNUSED(bitmap_t *dst), UNUSED(int x1), UNUSED(int y1), UNUSED(int x2), UNUSED(int y2), UNUSED(int xs), UNUSED(int ys))
{
2023-07-31 17:31:15 -04:00
//
}
void
2023-07-31 17:31:15 -04:00
stretch_blit(UNUSED(bitmap_t *src), UNUSED(bitmap_t *dst), UNUSED(int x1), UNUSED(int y1), UNUSED(int xs1), UNUSED(int ys1), UNUSED(int x2), UNUSED(int y2), UNUSED(int xs2), UNUSED(int ys2))
{
2023-07-31 17:31:15 -04:00
//
}
void
2023-07-31 17:31:15 -04:00
rectfill(UNUSED(bitmap_t *b), UNUSED(int x1), UNUSED(int y1), UNUSED(int x2), UNUSED(int y2), UNUSED(uint32_t col))
{
2023-07-31 17:31:15 -04:00
//
}
void
2023-07-31 17:31:15 -04:00
set_palette(UNUSED(PALETTE p))
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
{
2023-07-31 17:31:15 -04:00
//
Applied all mainline PCem commits; Added experimental NVidia Riva TNT2 emulation (patch from MoochMcGee); ASUS P/I-P54TP4XE, ASUS P/I-P55T2P4, and ASUS P/I-P55TVP4 are back; National Semiconductor PC87306 Super I/O chip now correctly reenables devices after a chip power cycle; Several FDC improvements and the behavior is now a bit closer to real hardware (based on actual tests); Added MR Intel Advanced/ATX with Microid Research BIOS with support for 4 floppy drives and up to 4 IDE controllers; Added floppy drives 3 and 4, bringing the maximum to 4; You can now connect hard disks to the tertiary IDE controller; Correct undocumented behavior of the LEA instruction with register is back on 286 and later CPU's; Pentium-rea models with Intel chipsets now have port 92 (with alternate reset and alternate A20 toggle); Overhauled DMA channel read and write routines and fixed cascading; Improved IMG detection of a bad BPB (or complete lack of a BPB); Added preliminary emulation of PS/2 1.44 MB and PC-98 1.25 MB 3-mode drives (both have an inverted DENSEL pin); Removed the incorrect Amstrad mouse patch from TheCollector1995; Fixed ATAPI CD-ROM disk change detection; Windows IOCTL CD-ROM handler now tries to use direct SCSI passthrough for more things, including obtaining CD-ROM capacity; The Diamond Stealth32 (ET4000/W32p) now also works correctly on the two Award SiS 496/497 boxes; The (S)VGA handler now converts 6-bit RAMDAC RGB channels to standard 8-bit RGB using a lookup table generated at emulator start, calculated using the correct intensity conversion method and treating intensity 64 as equivalent to 63; Moved a few options from the Configuration dialog box to the menu; SIO, PIIX, and PIIX3 now have the reset control register on port CF9 as they should; Several bugfixes.
2016-12-23 03:16:24 +01:00
}
void
destroy_bitmap(bitmap_t *b)
{
if ((b != NULL) && (b->dat != NULL))
2022-08-31 19:19:29 -04:00
free(b->dat);
if (b != NULL)
2022-08-31 19:19:29 -04:00
free(b);
}
bitmap_t *
create_bitmap(int x, int y)
{
Added the IBM 5161 ISA expansion for PC and XT; Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
bitmap_t *b = malloc(sizeof(bitmap_t) + (y * sizeof(uint32_t *)));
b->dat = malloc((size_t) x * y * 4);
2023-06-01 18:32:25 -04:00
for (int c = 0; c < y; c++)
2022-08-31 19:19:29 -04:00
b->line[c] = &(b->dat[c * x]);
b->w = x;
b->h = y;
2023-06-01 18:32:25 -04:00
return b;
}
void
video_monitor_init(int index)
{
memset(&monitors[index], 0, sizeof(monitor_t));
2022-08-31 19:19:29 -04:00
monitors[index].mon_xsize = 640;
monitors[index].mon_ysize = 480;
monitors[index].mon_res_x = 640;
monitors[index].mon_res_y = 480;
monitors[index].mon_scrnsz_x = 640;
monitors[index].mon_scrnsz_y = 480;
monitors[index].mon_efscrnsz_y = 480;
monitors[index].mon_unscaled_size_x = 480;
monitors[index].mon_unscaled_size_y = 480;
monitors[index].mon_bpp = 8;
monitors[index].mon_changeframecount = 2;
monitors[index].target_buffer = create_bitmap(2048, 2048);
monitors[index].mon_blit_data_ptr = calloc(1, sizeof(blit_data_t));
monitors[index].mon_blit_data_ptr->wake_blit_thread = thread_create_event();
monitors[index].mon_blit_data_ptr->blit_complete = thread_create_event();
monitors[index].mon_blit_data_ptr->buffer_not_in_use = thread_create_event();
2022-08-31 19:19:29 -04:00
monitors[index].mon_blit_data_ptr->thread_run = 1;
monitors[index].mon_blit_data_ptr->monitor_index = index;
monitors[index].mon_pal_lookup = calloc(sizeof(uint32_t), 256);
monitors[index].mon_cga_palette = calloc(1, sizeof(int));
monitors[index].mon_force_resize = 1;
monitors[index].mon_vid_type = VIDEO_FLAG_TYPE_NONE;
atomic_init(&doresize_monitors[index], 0);
2022-07-11 21:34:58 +06:00
atomic_init(&monitors[index].mon_screenshots, 0);
2022-08-31 19:19:29 -04:00
if (index >= 1)
ui_init_monitor(index);
2022-07-05 00:21:30 +06:00
monitors[index].mon_blit_data_ptr->blit_thread = thread_create(blit_thread, monitors[index].mon_blit_data_ptr);
}
void
video_monitor_close(int monitor_index)
{
2022-08-31 19:19:29 -04:00
if (monitors[monitor_index].target_buffer == NULL) {
return;
}
monitors[monitor_index].mon_blit_data_ptr->thread_run = 0;
thread_set_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread);
thread_wait(monitors[monitor_index].mon_blit_data_ptr->blit_thread);
2022-08-31 19:19:29 -04:00
if (monitor_index >= 1)
ui_deinit_monitor(monitor_index);
thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->buffer_not_in_use);
thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->blit_complete);
thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread);
free(monitors[monitor_index].mon_blit_data_ptr);
2022-08-31 19:19:29 -04:00
if (!monitors[monitor_index].mon_pal_lookup_static)
free(monitors[monitor_index].mon_pal_lookup);
if (!monitors[monitor_index].mon_cga_palette_static)
free(monitors[monitor_index].mon_cga_palette);
2022-07-05 00:21:30 +06:00
destroy_bitmap(monitors[monitor_index].target_buffer);
monitors[monitor_index].target_buffer = NULL;
memset(&monitors[monitor_index], 0, sizeof(monitor_t));
}
void
video_init(void)
{
uint8_t total[2] = { 0, 1 };
2023-08-21 20:25:05 -04:00
for (uint8_t c = 0; c < 16; c++) {
2022-08-31 19:19:29 -04:00
cga_2_table[c] = (total[(c >> 3) & 1] << 0) | (total[(c >> 2) & 1] << 8) | (total[(c >> 1) & 1] << 16) | (total[(c >> 0) & 1] << 24);
}
2023-08-21 20:25:05 -04:00
for (uint8_t c = 0; c < 64; c++) {
2022-08-31 19:19:29 -04:00
cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
cgapal[c + 64].b = (((c & 1) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
if ((c & 0x17) == 6)
cgapal[c + 64].g >>= 1;
}
2023-08-21 20:25:05 -04:00
for (uint8_t c = 0; c < 64; c++) {
2022-08-31 19:19:29 -04:00
cgapal[c + 128].r = (((c & 4) ? 2 : 0) | ((c & 0x20) ? 1 : 0)) * 21;
cgapal[c + 128].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21;
cgapal[c + 128].b = (((c & 1) ? 2 : 0) | ((c & 0x08) ? 1 : 0)) * 21;
}
2023-08-21 20:25:05 -04:00
for (uint8_t c = 0; c < 4; c++) {
for (uint8_t d = 0; d < 4; d++) {
2022-08-31 19:19:29 -04:00
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;
}
}
video_6to8 = malloc(4 * 256);
2023-08-21 20:25:05 -04:00
for (uint16_t c = 0; c < 256; c++)
2022-08-31 19:19:29 -04:00
video_6to8[c] = calc_6to8(c);
video_8togs = malloc(4 * 256);
2023-08-21 20:25:05 -04:00
for (uint16_t c = 0; c < 256; c++)
2022-08-31 19:19:29 -04:00
video_8togs[c] = c | (c << 16) | (c << 24);
video_8to32 = malloc(4 * 256);
2023-08-21 20:25:05 -04:00
for (uint16_t c = 0; c < 256; c++)
2022-08-31 19:19:29 -04:00
video_8to32[c] = calc_8to32(c);
video_15to32 = malloc(4 * 65536);
2023-08-21 20:25:05 -04:00
for (uint32_t c = 0; c < 65536; c++)
2022-08-31 19:19:29 -04:00
video_15to32[c] = calc_15to32(c & 0x7fff);
video_16to32 = malloc(4 * 65536);
2023-08-21 20:25:05 -04:00
for (uint32_t c = 0; c < 65536; c++)
2022-08-31 19:19:29 -04:00
video_16to32[c] = calc_16to32(c);
memset(monitors, 0, sizeof(monitors));
video_monitor_init(0);
}
void
video_close(void)
{
video_monitor_close(0);
free(video_16to32);
free(video_15to32);
free(video_8to32);
free(video_8togs);
free(video_6to8);
if (fontdatksc5601) {
2022-08-31 19:19:29 -04:00
free(fontdatksc5601);
fontdatksc5601 = NULL;
}
if (fontdatksc5601_user) {
2022-08-31 19:19:29 -04:00
free(fontdatksc5601_user);
fontdatksc5601_user = NULL;
}
}
uint8_t
video_force_resize_get_monitor(int monitor_index)
{
return monitors[monitor_index].mon_force_resize;
}
void
video_force_resize_set_monitor(uint8_t res, int monitor_index)
{
monitors[monitor_index].mon_force_resize = res;
}
void
loadfont_common(FILE *f, int format)
{
2023-06-01 18:32:25 -04:00
int c;
int d;
2022-02-20 02:26:27 -05:00
2022-08-31 19:19:29 -04:00
switch (format) {
case 0: /* MDA */
for (c = 0; c < 256; c++)
for (d = 0; d < 8; d++)
fontdatm[c][d] = fgetc(f) & 0xff;
for (c = 0; c < 256; c++)
for (d = 0; d < 8; d++)
fontdatm[c][d + 8] = fgetc(f) & 0xff;
(void) fseek(f, 4096 + 2048, SEEK_SET);
for (c = 0; c < 256; c++)
for (d = 0; d < 8; d++)
fontdat[c][d] = fgetc(f) & 0xff;
break;
case 1: /* 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 */
2022-09-21 18:53:41 -04:00
(void) !fread(&fontdatm[256 * d + c][0], 1, 16, f);
2022-08-31 19:19:29 -04:00
for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */
2022-09-21 18:53:41 -04:00
(void) !fread(&fontdat[256 * d + c][0], 1, 8, f);
2022-08-31 19:19:29 -04:00
fseek(f, 8, SEEK_CUR);
}
}
break;
default:
case 2: /* CGA */
for (c = 0; c < 256; c++)
for (d = 0; d < 8; d++)
fontdat[c][d] = fgetc(f) & 0xff;
break;
case 3: /* Wyse 700 */
for (c = 0; c < 512; c++)
for (d = 0; d < 32; d++)
fontdatw[c][d] = fgetc(f) & 0xff;
break;
case 4: /* MDSI Genius */
for (c = 0; c < 256; c++)
for (d = 0; d < 16; d++)
fontdat8x12[c][d] = fgetc(f) & 0xff;
break;
2022-09-18 17:17:41 -04:00
case 5: /* Toshiba 3100e */
2022-08-31 19:19:29 -04:00
for (d = 0; d < 2048; d += 512) { /* Four languages... */
for (c = d; c < d + 256; c++) {
(void) !fread(&fontdatm[c][8], 1, 8, f);
}
for (c = d + 256; c < d + 512; c++) {
(void) !fread(&fontdatm[c][8], 1, 8, f);
}
for (c = d; c < d + 256; c++) {
(void) !fread(&fontdatm[c][0], 1, 8, f);
}
for (c = d + 256; c < d + 512; c++) {
(void) !fread(&fontdatm[c][0], 1, 8, f);
}
fseek(f, 4096, SEEK_CUR); /* Skip blank section */
for (c = d; c < d + 256; c++) {
(void) !fread(&fontdat[c][0], 1, 8, f);
}
for (c = d + 256; c < d + 512; c++) {
(void) !fread(&fontdat[c][0], 1, 8, f);
}
}
break;
2022-08-31 19:19:29 -04:00
case 6: /* Korean KSC-5601 */
if (!fontdatksc5601)
fontdatksc5601 = malloc(16384 * sizeof(dbcs_font_t));
2022-02-20 02:26:27 -05:00
2022-08-31 19:19:29 -04:00
if (!fontdatksc5601_user)
fontdatksc5601_user = malloc(192 * sizeof(dbcs_font_t));
for (c = 0; c < 16384; c++) {
for (d = 0; d < 32; d++)
fontdatksc5601[c].chr[d] = fgetc(f) & 0xff;
}
break;
2022-08-31 19:19:29 -04:00
case 7: /* Sigma Color 400 */
/* The first 4k of the character ROM holds an 8x8 font */
for (c = 0; c < 256; c++) {
(void) !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++) {
if (fread(&fontdatm[c][0], 1, 16, f) != 16)
fatal("loadfont(): Error reading 8x16 font in Sigma Color 400 mode, c = %i\n", c);
}
break;
case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */
for (c = 0; c < 2048; c++) /* Allow up to 2048 chars */
for (d = 0; d < 8; d++)
fontdat[c][d] = fgetc(f) & 0xff;
break;
case 9: /* Image Manager 1024 native font */
for (c = 0; c < 256; c++)
(void) !fread(&fontdat12x18[c][0], 1, 36, f);
break;
2022-11-19 08:49:04 -05:00
case 10: /* Pravetz */
for (c = 0; c < 1024; c++) /* Allow up to 1024 chars */
for (d = 0; d < 8; d++)
fontdat[c][d] = fgetc(f) & 0xff;
break;
case 11: /* 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 */
(void) !fread(&fontdatm2[256 * d + c][0], 1, 16, f);
for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */
(void) !fread(&fontdat2[256 * d + c][0], 1, 8, f);
fseek(f, 8, SEEK_CUR);
}
}
break;
2022-08-31 19:19:29 -04:00
}
(void) fclose(f);
}
void
loadfont_ex(char *s, int format, int offset)
{
2023-08-21 20:25:05 -04:00
FILE *fp;
2022-02-20 02:26:27 -05:00
2023-08-21 20:25:05 -04:00
fp = rom_fopen(s, "rb");
if (fp == NULL)
2022-08-31 19:19:29 -04:00
return;
2023-08-21 20:25:05 -04:00
fseek(fp, offset, SEEK_SET);
loadfont_common(fp, format);
}
void
loadfont(char *s, int format)
{
loadfont_ex(s, format, 0);
}
uint32_t
video_color_transform(uint32_t color)
{
uint8_t *clr8 = (uint8_t *) &color;
2023-07-31 17:31:15 -04:00
#if 0
if (!video_grayscale && !invert_display)
return color;
#endif
if (video_grayscale) {
2022-08-31 19:19:29 -04:00
if (video_graytype) {
if (video_graytype == 1)
color = ((54 * (uint32_t) clr8[2]) + (183 * (uint32_t) clr8[1]) + (18 * (uint32_t) clr8[0])) / 255;
else
color = ((uint32_t) clr8[2] + (uint32_t) clr8[1] + (uint32_t) clr8[0]) / 3;
} else
color = ((76 * (uint32_t) clr8[2]) + (150 * (uint32_t) clr8[1]) + (29 * (uint32_t) clr8[0])) / 255;
switch (video_grayscale) {
case 2:
case 3:
case 4:
2023-07-31 17:31:15 -04:00
color = shade[video_grayscale][color];
2022-08-31 19:19:29 -04:00
break;
default:
clr8[3] = 0;
clr8[0] = color;
clr8[1] = clr8[2] = clr8[0];
break;
}
}
if (invert_display)
2022-08-31 19:19:29 -04:00
color ^= 0x00ffffff;
return color;
}