2013-07-06 04:37:13 +00:00
|
|
|
/*
|
2013-06-11 07:08:15 +00:00
|
|
|
* Apple // emulator for Linux: Video support
|
|
|
|
*
|
|
|
|
* Copyright 1994 Alexander Jean-Claude Bottema
|
|
|
|
* Copyright 1995 Stephen Lee
|
|
|
|
* Copyright 1997, 1998 Aaron Culliney
|
|
|
|
* Copyright 1998, 1999, 2000 Michael Deutschmann
|
|
|
|
*
|
|
|
|
* This software package is subject to the GNU General Public License
|
2013-07-06 04:37:13 +00:00
|
|
|
* version 2 or later (your choice) as published by the Free Software
|
2013-06-11 07:08:15 +00:00
|
|
|
* Foundation.
|
|
|
|
*
|
2013-07-06 04:37:13 +00:00
|
|
|
* THERE ARE NO WARRANTIES WHATSOEVER.
|
2013-06-11 07:08:15 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2014-01-23 04:42:34 +00:00
|
|
|
#include "common.h"
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2014-01-25 22:13:38 +00:00
|
|
|
static uint8_t vga_mem_page_0[SCANWIDTH*SCANHEIGHT]; /* page0 framebuffer */
|
|
|
|
static uint8_t vga_mem_page_1[SCANWIDTH*SCANHEIGHT]; /* page1 framebuffer */
|
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
#ifdef _640x400
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t video__wider_font[0x8000];
|
2013-06-11 07:08:15 +00:00
|
|
|
#endif /* _640x400 */
|
|
|
|
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t video__font[0x4000];
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* --- Precalculated hi-res page offsets given addr --- */
|
2013-07-06 04:37:13 +00:00
|
|
|
unsigned int video__screen_addresses[8192];
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t video__columns[8192];
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t *video__fb1,*video__fb2;
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
#ifdef _640x400
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t video__wider_hires_even[0x1000];
|
|
|
|
uint8_t video__wider_hires_odd[0x1000];
|
2013-06-11 07:08:15 +00:00
|
|
|
#endif
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t video__hires_even[0x800];
|
|
|
|
uint8_t video__hires_odd[0x800];
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t video__dhires1[256];
|
|
|
|
uint8_t video__dhires2[256];
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-11-27 20:43:58 +00:00
|
|
|
// Interface font
|
2014-01-25 22:13:38 +00:00
|
|
|
static uint8_t video__int_font[3][0x4000];
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
int video__current_page; /* Current visual page */
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-12-07 06:55:00 +00:00
|
|
|
int video__strictcolors = 1;// 0 is deprecated
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
void video_loadfont(int first,
|
|
|
|
int quantity,
|
2013-06-11 07:08:15 +00:00
|
|
|
const unsigned char *data,
|
|
|
|
int mode)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
int i,j;
|
|
|
|
unsigned char x,y,fg,bg;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
switch (mode)
|
2013-06-11 07:08:15 +00:00
|
|
|
{
|
|
|
|
case 2:
|
2013-07-06 04:37:13 +00:00
|
|
|
fg = COLOR_BLACK; bg = COLOR_LIGHT_WHITE; break;
|
2013-06-11 07:08:15 +00:00
|
|
|
case 3:
|
2013-07-06 04:37:13 +00:00
|
|
|
fg = COLOR_FLASHING_WHITE; bg = COLOR_FLASHING_BLACK; break;
|
|
|
|
default:
|
|
|
|
fg = COLOR_LIGHT_WHITE; bg = COLOR_BLACK; break;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
i = quantity * 8;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
while (i--)
|
2013-06-11 07:08:15 +00:00
|
|
|
{
|
|
|
|
j = 8;
|
|
|
|
x = data[i];
|
|
|
|
while (j--)
|
|
|
|
{
|
2013-07-06 04:37:13 +00:00
|
|
|
y = (x & 128) ? fg : bg;
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
#ifdef _640x400
|
2013-07-06 04:37:13 +00:00
|
|
|
video__wider_font[(first << 7) + (i << 4) + (j << 1)] =
|
|
|
|
video__wider_font[(first << 7) + (i << 4) + (j << 1) + 1] =
|
|
|
|
#endif /* _640x400 */
|
2013-06-11 07:08:15 +00:00
|
|
|
video__font[(first << 6) + (i << 3) + j] = y;
|
2013-07-06 04:37:13 +00:00
|
|
|
x <<= 1;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t video__odd_colors[2] = { COLOR_LIGHT_PURPLE, COLOR_LIGHT_BLUE };
|
|
|
|
uint8_t video__even_colors[2] = { COLOR_LIGHT_GREEN, COLOR_LIGHT_RED };
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* 40col/80col/lores/hires/dhires line offsets */
|
|
|
|
unsigned short video__line_offset[24] =
|
2013-07-06 04:37:13 +00:00
|
|
|
{ 0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380,
|
|
|
|
0x028, 0x0A8, 0x128, 0x1A8, 0x228, 0x2A8, 0x328, 0x3A8,
|
|
|
|
0x050, 0x0D0, 0x150, 0x1D0, 0x250, 0x2D0, 0x350, 0x3D0 };
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t video__dhires1[256] = {
|
2013-06-11 07:08:15 +00:00
|
|
|
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,
|
|
|
|
0x0,0x1,0x3,0x3,0x5,0x5,0x7,0x7,0x9,0x9,0xb,0xb,0xd,0xd,0xf,0xf,
|
|
|
|
0x0,0x1,0x2,0x3,0x6,0x5,0x6,0x7,0xa,0x9,0xa,0xb,0xe,0xd,0xe,0xf,
|
|
|
|
0x0,0x1,0x3,0x3,0x7,0x5,0x7,0x7,0xb,0x9,0xb,0xb,0xf,0xd,0xf,0xf,
|
|
|
|
0x0,0x1,0x2,0x3,0x4,0x4,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,
|
|
|
|
0x0,0x1,0x3,0x3,0x5,0x5,0x7,0x7,0xd,0x9,0xb,0xb,0xd,0xd,0xf,0xf,
|
|
|
|
0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0xe,0x9,0xa,0xb,0xe,0xd,0xe,0xf,
|
|
|
|
0x0,0x1,0x7,0x3,0x7,0x5,0x7,0x7,0xf,0x9,0xb,0xb,0xf,0xd,0xf,0xf,
|
|
|
|
};
|
|
|
|
|
2014-01-25 22:13:38 +00:00
|
|
|
uint8_t video__dhires2[256] = {
|
2013-06-11 07:08:15 +00:00
|
|
|
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x8,0x0,0xb,0x8,0xd,0x0,0x0,
|
|
|
|
0x1,0x1,0x1,0x1,0x0,0x5,0x1,0x1,0x0,0x9,0xb,0xb,0x0,0xd,0xf,0xf,
|
|
|
|
0x0,0x1,0x2,0x2,0x2,0x5,0x2,0x2,0x0,0xa,0xa,0xa,0xe,0xd,0x2,0x2,
|
|
|
|
0x3,0x3,0x3,0x3,0x7,0x5,0x7,0x7,0x0,0xb,0xb,0xb,0xf,0xd,0xf,0xf,
|
|
|
|
0x0,0x0,0x4,0x0,0x4,0x4,0x4,0x4,0xc,0x8,0x4,0x8,0xc,0xd,0x4,0x4,
|
|
|
|
0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,0xd,0x4,0x4,0x4,0xd,0xd,0x4,0x4,
|
|
|
|
0x6,0x6,0x6,0x2,0xe,0x6,0x6,0x6,0xe,0xe,0xa,0xa,0xe,0x6,0xe,0x6,
|
|
|
|
0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0xf,0xf,0xb,0xb,0xf,0xf,0xf,0xf,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
c_initialize_dhires_values()
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
static void c_initialize_dhires_values(void) {
|
|
|
|
int i;
|
|
|
|
/* int value, v; */
|
|
|
|
/* unsigned char locolor, hicolor; */
|
|
|
|
|
|
|
|
/* precalculate the colors for all the 256*8 bit combinations. */
|
|
|
|
/* for (value = 0x00, v = 0; value <= 0xFF; value++) { */
|
2013-07-06 04:37:13 +00:00
|
|
|
/* locolor = (value & 0x0F) | 0x10; */
|
|
|
|
/* hicolor = (value << 4) | 0x10; */
|
|
|
|
|
|
|
|
/* dhires_colors[v++] = locolor; */
|
|
|
|
/* dhires_colors[v++] = locolor; */
|
|
|
|
/* dhires_colors[v++] = locolor; */
|
|
|
|
/* dhires_colors[v++] = locolor; */
|
|
|
|
|
|
|
|
/* dhires_colors[v++] = hicolor; */
|
|
|
|
/* dhires_colors[v++] = hicolor; */
|
|
|
|
/* dhires_colors[v++] = hicolor; */
|
|
|
|
/* dhires_colors[v++] = hicolor; */
|
2013-06-11 07:08:15 +00:00
|
|
|
/* } */
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
for (i = 0; i < 0x80; i++)
|
|
|
|
{
|
|
|
|
video__dhires1[i+0x80] = video__dhires1[i];
|
|
|
|
video__dhires2[i+0x80] = video__dhires2[i];
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
c_initialize_hires_values()
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static void c_initialize_hires_values(void)
|
|
|
|
{
|
2013-07-06 04:37:13 +00:00
|
|
|
int value, b, v, e, /*color_toggle,*/ last_not_black;
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* precalculate the colors for all the 256*8 bit combinations. */
|
2013-07-06 04:37:13 +00:00
|
|
|
for (value = 0x00; value <= 0xFF; value++)
|
|
|
|
{
|
|
|
|
for (e = value * 8, last_not_black = 0, v = value, b = 0;
|
|
|
|
b < 7; b++, v >>= 1, e++)
|
|
|
|
{
|
|
|
|
if (v & 1)
|
|
|
|
{
|
|
|
|
video__hires_even[ e ] = last_not_black ?
|
|
|
|
COLOR_LIGHT_WHITE :
|
|
|
|
((b & 1) ?
|
|
|
|
((value & 0x80) ?
|
|
|
|
COLOR_LIGHT_RED :
|
|
|
|
COLOR_LIGHT_GREEN) :
|
|
|
|
((value & 0x80) ?
|
|
|
|
COLOR_LIGHT_BLUE :
|
|
|
|
COLOR_LIGHT_PURPLE));
|
|
|
|
|
|
|
|
video__hires_odd[ e ] = last_not_black ?
|
|
|
|
COLOR_LIGHT_WHITE :
|
|
|
|
((b & 1) ?
|
|
|
|
((value & 0x80) ?
|
|
|
|
COLOR_LIGHT_BLUE :
|
|
|
|
COLOR_LIGHT_PURPLE) :
|
|
|
|
((value & 0x80) ?
|
|
|
|
COLOR_LIGHT_RED :
|
|
|
|
COLOR_LIGHT_GREEN));
|
|
|
|
|
|
|
|
if (last_not_black && b > 0)
|
|
|
|
{
|
|
|
|
video__hires_even[ e - 1 ] = COLOR_LIGHT_WHITE,
|
|
|
|
video__hires_odd[ e - 1 ] = COLOR_LIGHT_WHITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
last_not_black = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
video__hires_even[ e ] = COLOR_BLACK,
|
|
|
|
video__hires_odd[ e ] = COLOR_BLACK,
|
|
|
|
last_not_black = 0;
|
|
|
|
}
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-12-07 06:55:00 +00:00
|
|
|
if (color_mode == COLOR_NONE) /* Black and White */
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
for (value = 0x00; value <= 0xFF; value++)
|
|
|
|
{
|
|
|
|
for (b = 0, e = value * 8; b < 7; b++, e++)
|
|
|
|
{
|
|
|
|
if (video__hires_even[ e ] != COLOR_BLACK)
|
|
|
|
{
|
|
|
|
video__hires_even[ e ] = COLOR_LIGHT_WHITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video__hires_odd[ e ] != COLOR_BLACK)
|
|
|
|
{
|
|
|
|
video__hires_odd[ e ] = COLOR_LIGHT_WHITE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-12-07 06:55:00 +00:00
|
|
|
#if 0
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (color_mode == LAZY_INTERP) /* Lazy Interpolated color */
|
2013-06-11 07:08:15 +00:00
|
|
|
{
|
|
|
|
for (value = 0x00; value <= 0xFF; value++)
|
|
|
|
{
|
|
|
|
for (b = 1, e = value * 8 + 1; b <= 5; b += 2, e += 2)
|
|
|
|
{
|
|
|
|
if (video__hires_even[ e ] == COLOR_BLACK &&
|
|
|
|
video__hires_even[ e - 1 ] != COLOR_BLACK &&
|
|
|
|
video__hires_even[ e + 1 ] != COLOR_BLACK)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
video__hires_even[ e ] =
|
|
|
|
video__hires_even[ e - 1 ];
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
if (video__hires_odd[ e ] == COLOR_BLACK &&
|
|
|
|
video__hires_odd[ e - 1 ] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[ e + 1 ] != COLOR_BLACK)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
video__hires_odd[ e ] =
|
|
|
|
video__hires_odd[ e - 1 ];
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
for (b = 0, e = value * 8; b <= 6; b += 2, e += 2)
|
|
|
|
{
|
|
|
|
if (video__hires_odd[ e ] == COLOR_BLACK)
|
|
|
|
{
|
|
|
|
if (b > 0 && b < 6)
|
|
|
|
{
|
|
|
|
if (video__hires_even[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e+1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_even[e-1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_even[e] =
|
|
|
|
video__hires_even[e-1];
|
|
|
|
}
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (b == 0)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
if (video__hires_even[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_even[e] =
|
|
|
|
video__hires_even[e+1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (video__hires_even[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e-1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_even[ e ] =
|
|
|
|
video__hires_even[ e - 1 ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video__hires_odd[ e ] == COLOR_BLACK)
|
|
|
|
{
|
|
|
|
if (b > 0 && b < 6)
|
|
|
|
{
|
|
|
|
if (video__hires_odd[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e+1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_odd[e-1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_odd[e] =
|
|
|
|
video__hires_odd[e-1];
|
|
|
|
}
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (b == 0)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
if (video__hires_odd[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_odd[e] =
|
|
|
|
video__hires_odd[e+1];
|
|
|
|
}
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (video__hires_odd[e-1] != COLOR_BLACK &&
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_odd[e-1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_odd[e] =
|
|
|
|
video__hires_odd[e-1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-12-07 06:55:00 +00:00
|
|
|
#endif
|
|
|
|
else if (color_mode == COLOR_INTERP) /* Color and strict interpolation */
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
for (value = 0x00; value <= 0xFF; value++)
|
|
|
|
{
|
|
|
|
for (b = 1, e = value * 8 + 1; b <= 5; b += 2, e += 2)
|
|
|
|
{
|
|
|
|
if (video__hires_even[e] == COLOR_BLACK)
|
|
|
|
{
|
|
|
|
if (video__hires_even[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e-1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_even[e] =
|
|
|
|
video__hires_even[e-1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-06-11 07:08:15 +00:00
|
|
|
video__hires_even[e-1] != COLOR_BLACK &&
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_even[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e-1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_even[e+1] == COLOR_LIGHT_WHITE)
|
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
video__hires_even[e] =
|
|
|
|
video__hires_even[e-1];
|
2013-07-06 04:37:13 +00:00
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_even[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e-1] == COLOR_LIGHT_WHITE &&
|
2013-06-11 07:08:15 +00:00
|
|
|
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
video__hires_even[e] =
|
|
|
|
video__hires_even[e+1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_even[e-1] == COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_even[e+1] == COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_even[e] = (value & 0x80)
|
|
|
|
? COLOR_LIGHT_BLUE : COLOR_LIGHT_PURPLE;
|
|
|
|
}
|
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (video__hires_odd[e] == COLOR_BLACK)
|
|
|
|
{
|
|
|
|
if (video__hires_odd[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e-1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_odd[e] =
|
|
|
|
video__hires_odd[e-1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-06-11 07:08:15 +00:00
|
|
|
video__hires_odd[e-1] != COLOR_BLACK &&
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_odd[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e-1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_odd[e+1] == COLOR_LIGHT_WHITE)
|
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
video__hires_odd[e] =
|
|
|
|
video__hires_odd[e-1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_odd[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e-1] == COLOR_LIGHT_WHITE &&
|
2013-06-11 07:08:15 +00:00
|
|
|
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
video__hires_odd[e] =
|
|
|
|
video__hires_odd[e+1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_odd[e-1] == COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_odd[e+1] == COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_odd[e] = (value & 0x80)
|
|
|
|
? COLOR_LIGHT_RED : COLOR_LIGHT_GREEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (b = 0, e = value * 8; b <= 6; b += 2, e += 2)
|
|
|
|
{
|
|
|
|
if (video__hires_even[ e ] == COLOR_BLACK)
|
|
|
|
{
|
|
|
|
if (b > 0 && b < 6)
|
|
|
|
{
|
|
|
|
if (video__hires_even[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e-1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_even[e] =
|
|
|
|
video__hires_even[e-1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_even[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e-1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_even[e+1] == COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_even[e] =
|
|
|
|
video__hires_even[e-1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_even[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_even[e-1] == COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_even[e+1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_even[e] =
|
|
|
|
video__hires_even[e+1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_even[e-1] == COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_even[e+1] == COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_even[e] = (value & 0x80)
|
|
|
|
? COLOR_LIGHT_RED : COLOR_LIGHT_GREEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (video__hires_odd[e] == COLOR_BLACK)
|
|
|
|
{
|
|
|
|
if (b > 0 && b < 6)
|
|
|
|
{
|
|
|
|
if (video__hires_odd[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e-1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_odd[e] =
|
|
|
|
video__hires_odd[e-1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_odd[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e-1] != COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_odd[e+1] == COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_odd[e] =
|
|
|
|
video__hires_odd[e-1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_odd[e-1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e+1] != COLOR_BLACK &&
|
|
|
|
video__hires_odd[e-1] == COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_odd[e+1] != COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_odd[e] =
|
|
|
|
video__hires_odd[e+1];
|
|
|
|
}
|
2013-11-26 22:41:43 +00:00
|
|
|
else if (
|
2013-07-06 04:37:13 +00:00
|
|
|
video__hires_odd[e-1] == COLOR_LIGHT_WHITE &&
|
|
|
|
video__hires_odd[e+1] == COLOR_LIGHT_WHITE)
|
|
|
|
{
|
|
|
|
video__hires_odd[e] = (value & 0x80)
|
|
|
|
? COLOR_LIGHT_BLUE : COLOR_LIGHT_PURPLE;
|
|
|
|
}
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
#ifdef _640x400
|
|
|
|
/* *2 for 640x400 */
|
2013-07-06 04:37:13 +00:00
|
|
|
for (b=0, e=0; b<4096; b++, e++)
|
|
|
|
{
|
|
|
|
video__wider_hires_even[b] = video__hires_even[e];
|
|
|
|
video__wider_hires_odd[b] = video__hires_odd[e];
|
2013-06-11 07:08:15 +00:00
|
|
|
b++;
|
2013-07-06 04:37:13 +00:00
|
|
|
video__wider_hires_even[b] = video__hires_even[e];
|
|
|
|
video__wider_hires_odd[b] = video__hires_odd[e];
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2013-07-06 04:37:13 +00:00
|
|
|
|
2013-06-11 07:08:15 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
c_initialize_row_col_tables()
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
static void c_initialize_row_col_tables(void)
|
|
|
|
{
|
|
|
|
int x, y, off, i;
|
|
|
|
|
|
|
|
/* hires page offsets. initialize to invalid values. */
|
2013-07-06 04:37:13 +00:00
|
|
|
for (i = 0; i < 8192; i++)
|
|
|
|
{
|
|
|
|
video__screen_addresses[i] = -1;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
for (y = 0; y < 24; y++)
|
|
|
|
{
|
|
|
|
for (off = 0; off < 8; off++)
|
|
|
|
{
|
|
|
|
for (x = 0; x < 40; x++)
|
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
#ifdef _640x400
|
2013-07-06 04:37:13 +00:00
|
|
|
video__screen_addresses[video__line_offset[y] + 0x400*off + x ] =
|
|
|
|
(y*16 + 2*off /* + 8*/) * SCANWIDTH + x*14 + 4;
|
2013-06-11 07:08:15 +00:00
|
|
|
#else
|
2013-07-06 04:37:13 +00:00
|
|
|
video__screen_addresses[video__line_offset[y] + 0x400*off + x ] =
|
|
|
|
(y*8 + off + 4) * 320 + x*7 + 20;
|
2013-06-11 07:08:15 +00:00
|
|
|
#endif
|
2013-07-06 04:37:13 +00:00
|
|
|
video__columns[video__line_offset[y] + 0x400*off + x] =
|
2014-01-25 22:13:38 +00:00
|
|
|
(uint8_t)x;
|
2013-07-06 04:37:13 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void c_initialize_tables_video(void) {
|
2013-07-06 04:37:13 +00:00
|
|
|
int x, y, i;
|
2013-06-11 07:08:15 +00:00
|
|
|
|
|
|
|
/* initialize text/lores & hires graphics */
|
2013-07-06 04:37:13 +00:00
|
|
|
for (y = 0; y < 24; y++) /* 24 rows */
|
|
|
|
{
|
|
|
|
for (x = 0; x < 40; x++) /* 40 cols */
|
|
|
|
{
|
|
|
|
if (apple_mode == IIE_MODE)
|
|
|
|
{
|
|
|
|
/* //e mode: text/lores page 0 */
|
|
|
|
cpu65_vmem[ video__line_offset[ y ] + x + 0x400].w =
|
|
|
|
(y < 20) ? video__write_2e_text0 :
|
|
|
|
video__write_2e_text0_mixed;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* ][+ modes: text/lores page 0 */
|
|
|
|
cpu65_vmem[ video__line_offset[ y ] + x + 0x400].w =
|
|
|
|
(y < 20) ? video__write_text0 :
|
|
|
|
video__write_text0_mixed;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (apple_mode == IIE_MODE)
|
|
|
|
{
|
|
|
|
cpu65_vmem[ video__line_offset[ y ] + x + 0x800].w =
|
|
|
|
(y < 20) ? video__write_2e_text1 :
|
|
|
|
video__write_2e_text1_mixed;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* ][+ modes: text/lores page 1 in main memory */
|
|
|
|
cpu65_vmem[ video__line_offset[ y ] + x + 0x800].w =
|
|
|
|
(y < 20) ? video__write_text1 :
|
|
|
|
video__write_text1_mixed;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
/* //e mode: hires/double hires page 0 */
|
|
|
|
if (apple_mode == IIE_MODE)
|
|
|
|
{
|
|
|
|
cpu65_vmem[ 0x2000 + video__line_offset[ y ]
|
|
|
|
+ 0x400 * i + x ].w =
|
|
|
|
(y < 20) ? ((x & 1) ? video__write_2e_odd0 :
|
|
|
|
video__write_2e_even0)
|
|
|
|
: ((x & 1) ? video__write_2e_odd0_mixed :
|
|
|
|
video__write_2e_even0_mixed);
|
|
|
|
}
|
|
|
|
/* ][+ modes: hires page 0 */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu65_vmem[ 0x2000 + video__line_offset[ y ]
|
|
|
|
+ 0x400 * i + x ].w =
|
|
|
|
(y < 20) ? ((x & 1) ? video__write_odd0 :
|
|
|
|
video__write_even0)
|
|
|
|
: ((x & 1) ? video__write_odd0_mixed :
|
|
|
|
video__write_even0_mixed);
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
if (apple_mode == IIE_MODE)
|
|
|
|
{
|
|
|
|
cpu65_vmem[ 0x4000 + video__line_offset[ y ]
|
|
|
|
+ 0x400 * i + x ].w =
|
|
|
|
(y < 20) ? ((x & 1) ? video__write_2e_odd1 :
|
|
|
|
video__write_2e_even1)
|
|
|
|
: ((x & 1) ? video__write_2e_odd1_mixed :
|
|
|
|
video__write_2e_even1_mixed);
|
|
|
|
}
|
|
|
|
/* ][+ modes: hires page 1 */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cpu65_vmem[ 0x4000 + video__line_offset[ y ]
|
|
|
|
+ 0x400 * i + x ].w =
|
|
|
|
(y < 20) ? ((x & 1) ? video__write_odd1 :
|
|
|
|
video__write_even1)
|
|
|
|
: ((x & 1) ? video__write_odd1_mixed :
|
|
|
|
video__write_even1_mixed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void video_set(int flags)
|
|
|
|
{
|
2013-12-07 06:55:00 +00:00
|
|
|
video__strictcolors = (color_mode == COLOR_INTERP) ? 2 : 1;
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
c_initialize_hires_values(); /* precalculate hires values */
|
|
|
|
c_initialize_row_col_tables(); /* precalculate hires offsets */
|
|
|
|
c_initialize_tables_video(); /* memory jump tables for video */
|
2013-06-11 07:08:15 +00:00
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
c_initialize_dhires_values(); /* set up dhires colors */
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void video_loadfont_int(int first, int quantity, const unsigned char *data)
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
2013-06-11 07:08:15 +00:00
|
|
|
int i,j;
|
|
|
|
unsigned char x;
|
|
|
|
int y;
|
|
|
|
|
|
|
|
i = quantity * 8;
|
|
|
|
|
2013-07-06 04:37:13 +00:00
|
|
|
while (i--)
|
2013-06-11 07:08:15 +00:00
|
|
|
{
|
|
|
|
j = 8;
|
|
|
|
x = data[i];
|
|
|
|
while (j--)
|
|
|
|
{
|
2013-07-06 04:37:13 +00:00
|
|
|
y = (first << 6) + (i << 3) + j;
|
|
|
|
if (x & 128)
|
|
|
|
{
|
|
|
|
video__int_font[0][y] =
|
|
|
|
video__int_font[1][y] = COLOR_LIGHT_GREEN;
|
|
|
|
video__int_font[2][y] = COLOR_LIGHT_RED;
|
|
|
|
}
|
2013-06-11 07:08:15 +00:00
|
|
|
else
|
2013-07-06 04:37:13 +00:00
|
|
|
{
|
|
|
|
video__int_font[0][y] =
|
|
|
|
video__int_font[2][y] = COLOR_BLACK;
|
|
|
|
video__int_font[1][y] = COLOR_MEDIUM_BLUE;
|
|
|
|
}
|
|
|
|
x <<= 1;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-27 20:43:58 +00:00
|
|
|
static void c_interface_print_char80_line(
|
2013-07-06 04:37:13 +00:00
|
|
|
unsigned char **d, unsigned char **s)
|
2013-06-11 07:08:15 +00:00
|
|
|
{
|
|
|
|
#ifdef _640x400
|
2013-07-06 04:37:13 +00:00
|
|
|
*((unsigned int *)(*d)) = *((unsigned int *)(*s)); /*32bits*/
|
2013-06-11 07:08:15 +00:00
|
|
|
*d += 4, *s += 4;
|
2013-07-06 04:37:13 +00:00
|
|
|
*((unsigned short *)(*d)) = *((unsigned short *)(*s)); /*16bits*/
|
2013-11-27 20:43:58 +00:00
|
|
|
*d += 2, *s += 2;
|
|
|
|
*((unsigned char *)(*d)) = *((unsigned char *)(*s)); /*8bits*/
|
|
|
|
*d += SCANWIDTH-6, *s -= 6;
|
|
|
|
#endif
|
2013-07-06 04:37:13 +00:00
|
|
|
*((unsigned int *)(*d)) = *((unsigned int *)(*s)); /*32bits*/
|
2013-06-11 07:08:15 +00:00
|
|
|
*d += 4, *s += 4;
|
2013-07-06 04:37:13 +00:00
|
|
|
*((unsigned short *)(*d)) = *((unsigned short *)(*s)); /*16bits*/
|
2013-06-11 07:08:15 +00:00
|
|
|
*d += 2, *s += 2;
|
2013-07-06 04:37:13 +00:00
|
|
|
*((unsigned char *)(*d)) = *((unsigned char *)(*s)); /*8bits*/
|
2013-11-27 20:43:58 +00:00
|
|
|
*d += SCANWIDTH-6, *s += 2;
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void video_plotchar( int x, int y, int scheme, unsigned char c )
|
|
|
|
{
|
|
|
|
int off;
|
|
|
|
unsigned char *d;
|
|
|
|
unsigned char *s;
|
|
|
|
|
|
|
|
#ifdef _640x400
|
2013-11-27 20:43:58 +00:00
|
|
|
off = y * SCANWIDTH * 16 + x * 7 + 4;
|
|
|
|
s = video__int_font[scheme] + c * 64;
|
2013-06-11 07:08:15 +00:00
|
|
|
#else
|
2013-11-27 20:43:58 +00:00
|
|
|
off = y * SCANWIDTH * 8 + x * 7 + /*WtF?*/1300;
|
2013-06-11 07:08:15 +00:00
|
|
|
s = video__int_font[scheme] + c * 64;
|
|
|
|
#endif
|
|
|
|
d = video__fb1 + off;
|
|
|
|
|
2013-11-27 20:43:58 +00:00
|
|
|
c_interface_print_char80_line(&d,&s);
|
|
|
|
c_interface_print_char80_line(&d,&s);
|
|
|
|
c_interface_print_char80_line(&d,&s);
|
|
|
|
c_interface_print_char80_line(&d,&s);
|
|
|
|
c_interface_print_char80_line(&d,&s);
|
|
|
|
c_interface_print_char80_line(&d,&s);
|
|
|
|
c_interface_print_char80_line(&d,&s);
|
|
|
|
c_interface_print_char80_line(&d,&s);
|
2013-06-11 07:08:15 +00:00
|
|
|
}
|
2014-01-25 22:13:38 +00:00
|
|
|
|
2014-03-23 21:43:19 +00:00
|
|
|
#ifdef VIDEO_X11
|
|
|
|
extern void X11_video_init();
|
|
|
|
extern void X11_video_shutdown();
|
|
|
|
#endif
|
2014-01-25 22:13:38 +00:00
|
|
|
void video_init() {
|
|
|
|
|
|
|
|
video__fb1 = vga_mem_page_0;
|
|
|
|
video__fb2 = vga_mem_page_1;
|
|
|
|
|
|
|
|
// reset Apple2 softframebuffers
|
|
|
|
memset(video__fb1,0,SCANWIDTH*SCANHEIGHT);
|
|
|
|
memset(video__fb2,0,SCANWIDTH*SCANHEIGHT);
|
|
|
|
|
2014-03-23 21:43:19 +00:00
|
|
|
#ifdef VIDEO_X11
|
|
|
|
X11_video_init();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void video_shutdown(void)
|
|
|
|
{
|
|
|
|
#ifdef VIDEO_X11
|
|
|
|
X11_video_shutdown();
|
|
|
|
#endif
|
2014-01-25 22:13:38 +00:00
|
|
|
}
|
|
|
|
|
2014-03-30 18:01:05 +00:00
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
video_setpage(p): Switch to screen page p
|
|
|
|
------------------------------------------------------------------------- */
|
|
|
|
void video_setpage(int p)
|
|
|
|
{
|
|
|
|
video__current_page = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint8_t * const video_current_framebuffer() {
|
|
|
|
return !video__current_page ? video__fb1 : video__fb2;
|
|
|
|
}
|
|
|
|
|