mirror of
https://github.com/AppleWin/AppleWin.git
synced 2024-12-23 00:30:17 +00:00
For the RGB hires look-up table: - extended to include the previous video byte's high bit - so it's now: {previous high bit + prev 2 video bits + next 2 video bits} & current byte For all the RGB look-up tables: - reduced from 512 to 256 lines (only 256 were being used, so it was just wasting space) Refactored CopyMixedSource(): - fixed the Rainbow demo (#627) - sped up in Debug config Bumped version to 1.28.3.1.
This commit is contained in:
parent
9a4d257418
commit
b87ebb7514
@ -1,4 +1,4 @@
|
||||
#define APPLEWIN_VERSION 1,28,3,0
|
||||
#define APPLEWIN_VERSION 1,28,3,1
|
||||
|
||||
#define xstr(a) str(a)
|
||||
#define str(a) #a
|
||||
|
@ -8,13 +8,17 @@
|
||||
#include "RGBMonitor.h"
|
||||
#include "YamlHelper.h"
|
||||
|
||||
const int SRCOFFS_LORES = 0; // 0
|
||||
const int SRCOFFS_HIRES = (SRCOFFS_LORES + 16); // 16
|
||||
const int SRCOFFS_HIRES2 = (SRCOFFS_HIRES + 512); // 528 // Style = Vertical Blend, 280-pixel (from 1.25)
|
||||
const int SRCOFFS_DHIRES = (SRCOFFS_HIRES2 + 512); // 1040
|
||||
const int SRCOFFS_TOTAL = (SRCOFFS_DHIRES + 2560); // 3600
|
||||
const int HIRES_COLUMN_SUBUNIT_SIZE = 16;
|
||||
const int HIRES_COLUMN_UNIT_SIZE = (HIRES_COLUMN_SUBUNIT_SIZE)*2;
|
||||
const int HIRES_NUMBER_COLUMNS = (1<<5); // 5 bits
|
||||
|
||||
const int MAX_SOURCE_Y = 512;
|
||||
|
||||
const int SRCOFFS_LORES = 0; // 0
|
||||
const int SRCOFFS_HIRES = (SRCOFFS_LORES + 16); // 16
|
||||
const int SRCOFFS_DHIRES = (SRCOFFS_HIRES + (HIRES_NUMBER_COLUMNS*HIRES_COLUMN_UNIT_SIZE)); // 1040
|
||||
const int SRCOFFS_TOTAL = (SRCOFFS_DHIRES + 2560); // 3600
|
||||
|
||||
const int MAX_SOURCE_Y = 256;
|
||||
static LPBYTE g_aSourceStartofLine[ MAX_SOURCE_Y ];
|
||||
#define SETSOURCEPIXEL(x,y,c) g_aSourceStartofLine[(y)][(x)] = (c)
|
||||
|
||||
@ -42,12 +46,12 @@ enum Color_Palette_Index_e
|
||||
#endif
|
||||
|
||||
// TV emu
|
||||
, HGR_GREY1
|
||||
, HGR_GREY2
|
||||
, HGR_YELLOW
|
||||
, HGR_AQUA
|
||||
, HGR_PURPLE
|
||||
, HGR_PINK
|
||||
, HGR_GREY1
|
||||
, HGR_GREY2
|
||||
, HGR_YELLOW
|
||||
, HGR_AQUA
|
||||
, HGR_PURPLE
|
||||
, HGR_PINK
|
||||
// lores & dhires
|
||||
, BLACK
|
||||
, DEEP_RED
|
||||
@ -195,10 +199,9 @@ static void V_CreateLookup_DoubleHires ()
|
||||
}
|
||||
#endif
|
||||
|
||||
int y = byteval << 1;
|
||||
int y = byteval;
|
||||
for (int x = 0; x < SIZE; x++) {
|
||||
SETSOURCEPIXEL(SRCOFFS_DHIRES+coloffs+x,y ,DoubleHiresPalIndex[ color[x] ]);
|
||||
SETSOURCEPIXEL(SRCOFFS_DHIRES+coloffs+x,y+1,DoubleHiresPalIndex[ color[x] ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -218,153 +221,89 @@ void V_CreateLookup_Lores()
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define HALF_PIXEL_SOLID 1
|
||||
#define HALF_PIXEL_BLEED 0
|
||||
// Lookup Table:
|
||||
// y (0-255) * 32 columns of 32 bytes
|
||||
// . each column is: high-bit (prev byte) & 2 pixels from previous byte & 2 pixels from next byte
|
||||
// . each 32-byte unit is 2 * 16-byte sub-units: 16 bytes for even video byte & 16 bytes for odd video byte
|
||||
// . where 16 bytes represent the 7 Apple pixels, expanded to 14 pixels
|
||||
// currHighBit=0: {14 pixels + 2 pad} * 2
|
||||
// currHighBit=1: {1 pixel + 14 pixels + 1 pad} * 2
|
||||
// . and each byte is an index into the colour palette
|
||||
|
||||
void V_CreateLookup_HiResHalfPixel_Authentic(VideoType_e videoType) // Colors are solid (100% coverage)
|
||||
void V_CreateLookup_HiResHalfPixel_Authentic(VideoType_e videoType)
|
||||
{
|
||||
// 2-bits from previous byte, 2-bits from next byte = 2^4 = 16 total permutations
|
||||
for (int iColumn = 0; iColumn < 16; iColumn++)
|
||||
// high-bit & 2-bits from previous byte, 2-bits from next byte = 2^5 = 32 total permutations
|
||||
for (int iColumn = 0; iColumn < HIRES_NUMBER_COLUMNS; iColumn++)
|
||||
{
|
||||
int offsetx = iColumn << 5; // every column is 32 bytes wide -- 7 apple pixels = 14 pixels + 2 pad + 14 pixels + 2 pad
|
||||
const int offsetx = iColumn * HIRES_COLUMN_UNIT_SIZE; // every column is 32 bytes wide
|
||||
const int prevHighBit = (iColumn >= 16) ? 1 : 0;
|
||||
int aPixels[11]; // c2 c3 b6 b5 b4 b3 b2 b1 b0 c0 c1
|
||||
|
||||
for (unsigned iByte = 0; iByte < 256; iByte++)
|
||||
aPixels[ 0] = iColumn & 4; // previous byte, 2nd last pixel
|
||||
aPixels[ 1] = iColumn & 8; // previous byte, last pixel
|
||||
aPixels[ 9] = iColumn & 1; // next byte, first pixel
|
||||
aPixels[10] = iColumn & 2; // next byte, second pixel
|
||||
|
||||
for (unsigned int iByte = 0; iByte < 256; iByte++)
|
||||
{
|
||||
int aPixels[11]; // c2 c1 b7 b6 b5 b4 b3 b2 b1 b0 c8 c4
|
||||
|
||||
/*
|
||||
aPixel[i]
|
||||
A 9|8 7 6 5 4 3 2|1 0
|
||||
Z W|b b b b b b b|X Y
|
||||
----+-------------+----
|
||||
prev| existing |next
|
||||
bits| hi-res byte |bits
|
||||
|
||||
Legend:
|
||||
XYZW = iColumn in binary
|
||||
b = Bytes in binary
|
||||
*/
|
||||
// aPixel[] = 48bbbbbbbb12, where b = iByte in binary, # is bit-n of column
|
||||
aPixels[ 0] = iColumn & 4; // previous byte, 2nd last pixel
|
||||
aPixels[ 1] = iColumn & 8; // previous byte, last pixel
|
||||
aPixels[ 9] = iColumn & 1; // next byte, first pixel
|
||||
aPixels[10] = iColumn & 2; // next byte, second pixel
|
||||
|
||||
// Convert raw pixel Byte value to binary and stuff into bit array of pixels on off
|
||||
int nBitMask = 1;
|
||||
int iPixel;
|
||||
for (iPixel = 2; iPixel < 9; iPixel++)
|
||||
// Convert raw pixel iByte value to binary and stuff into bit array of pixels on off
|
||||
for (int iPixel = 2, nBitMask = 1; iPixel < 9; iPixel++)
|
||||
{
|
||||
aPixels[iPixel] = ((iByte & nBitMask) != 0);
|
||||
nBitMask <<= 1;
|
||||
}
|
||||
|
||||
int hibit = (iByte >> 7) & 1; // ((iByte & 0x80) != 0);
|
||||
int x = 0;
|
||||
int y = iByte << 1;
|
||||
const int currHighBit = (iByte >> 7) & 1;
|
||||
const int y = iByte;
|
||||
|
||||
/* Test cases
|
||||
81 blue
|
||||
2000:D5 AA D5 AA
|
||||
82 orange
|
||||
2800:AA D5 AA D5
|
||||
FF white bleed "thru"
|
||||
3000:7F 80 7F 80
|
||||
3800:FF 80 FF 80
|
||||
2028:80 7F 80 7F
|
||||
2828:80 FF 80 FF
|
||||
Edge Case for Half Luminance !
|
||||
2000:C4 00 // Green HalfLumBlue
|
||||
2400:C4 80 // Green Green
|
||||
Edge Case for Color Bleed !
|
||||
2000:40 00
|
||||
2400:40 80
|
||||
Nox Archaist (GH#616)
|
||||
2000:00 40 9E // Green Black White
|
||||
*/
|
||||
|
||||
// Fixup missing pixels that normally have been scan-line shifted -- Apple "half-pixel" -- but cross 14-pixel boundaries.
|
||||
if( hibit )
|
||||
// Fixup missing pixels that normally have been scan-line shifted -- Apple "half-pixel" -- but crosses video byte boundaries.
|
||||
// NB. Setup first byte in each 16-byte sub-unit
|
||||
if( currHighBit )
|
||||
{
|
||||
if ( aPixels[1] ) // preceding pixel on?
|
||||
#if 0 // Optimization: Doesn't seem to matter if we ignore the 2 pixels of the next byte
|
||||
for (iPixel = 0; iPixel < 9; iPixel++) // NOTE: You MUST start with the preceding 2 pixels !!!
|
||||
if (aPixels[iPixel]) // pixel on
|
||||
#endif
|
||||
if ( aPixels[1] ) // prev pixel on?
|
||||
{
|
||||
if (aPixels[2] || aPixels[0]) // White if pixel from previous byte and first pixel of this byte is on
|
||||
{
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+0 ,y , HGR_WHITE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+HIRES_COLUMN_SUBUNIT_SIZE,y , HGR_WHITE );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !prevHighBit ) // GH#616
|
||||
{
|
||||
if (aPixels[2] || aPixels[0]) // White if pixel from previous byte and first pixel of this byte is on
|
||||
{
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , HGR_WHITE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, HGR_WHITE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , HGR_WHITE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, HGR_WHITE );
|
||||
} else { // Optimization: odd = (iPixel & 1); if (!odd) case is same as if(odd) !!! // Reference: Gumball - Gumball Machine
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , HGR_ORANGE ); // left half of orange pixels
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, HGR_ORANGE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , HGR_BLUE ); // right half of blue pixels 4, 11, 18, ...
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, HGR_BLUE );
|
||||
}
|
||||
// colour the half-pixel black (was orange - not good for Nox Archaist, eg. 2000:00 40 E0; 2000:00 40 9E)
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+0 ,y , HGR_BLACK );
|
||||
}
|
||||
#if HALF_PIXEL_SOLID
|
||||
// Test Patterns
|
||||
// 81 blue
|
||||
// 2000:D5 AA D5 AA -> 2001:AA D5 should not have black gap, should be blue
|
||||
// 82 orange
|
||||
// 2800:AA D5 AA D5
|
||||
// Game: Elite -- Loading Logo
|
||||
// 2444:BB F7 -> 2000:BB F7 // Should not have orange in-between gap -- Elite "Firebird" Logo
|
||||
// -> 2400:00 BB F7 // Should not have blue in-between gap )
|
||||
// 21D0:C0 00 -> HalfLumBlue
|
||||
// 25D0:C0 D0 88 -> Blue black orange black orange
|
||||
// 29D0:C0 90 88 -> Blue black orange
|
||||
// Game: Ultima 4 -- Ultima 4 Logo - bottom half of screen has a "mini-game" / demo -- far right has tree and blue border
|
||||
// 2176:2A AB green black_gap white blue_border // Should have black gap between green and white
|
||||
else
|
||||
{
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+0 ,y , HGR_ORANGE ); // left half of orange pixels
|
||||
}
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+HIRES_COLUMN_SUBUNIT_SIZE,y , HGR_BLUE ); // right half of blue pixels 4, 11, 18, ...
|
||||
}
|
||||
}
|
||||
else if ( aPixels[0] ) // prev prev pixel on
|
||||
{
|
||||
// Game: Gumball
|
||||
// 218E:AA 97 => 2000: A9 87 orange_white // Should have no gap between orange and white
|
||||
// 229A:AB A9 87 -> 2000: 00 A9 87 white orange black blue_white // Should have no gap between blue and white
|
||||
// 2001:BB F7 white blue white (Gumball Intermission)
|
||||
// Torture Half-Pixel HGR Tests: This is a real bitch to solve -- we really need to check:
|
||||
// if (hibit_prev_byte && !aPixels[iPixel-3] && aPixels[iPixel-2] && !aPixels[iPixel] && hibit_this_byte) then set first half-pixel of this byte to either blue or orange
|
||||
// 2000:A9 87 halfblack blue black black orange black orange black
|
||||
// 2400:BB F7 halfblack white white black white white white halfblack
|
||||
// or
|
||||
// 2000:A0 83 orange should "bleed" thru
|
||||
// 2400:B0 83 should have black gap
|
||||
|
||||
if ( aPixels[2] )
|
||||
#if HALF_PIXEL_BLEED // No Half-Pixel Bleed
|
||||
if ( aPixels[3] ) {
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , DARK_BLUE ); // Gumball: 229A: AB A9 87
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, DARK_BLUE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , BROWN ); // half luminance red Elite: 2444: BB F7
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, BROWN ); // half luminance red Gumball: 218E: AA 97
|
||||
} else {
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , HGR_BLUE ); // 2000:D5 AA D5
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, HGR_BLUE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , HGR_ORANGE ); // 2000: AA D5
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, HGR_ORANGE );
|
||||
}
|
||||
#else
|
||||
{
|
||||
if ((videoType == VT_COLOR_MONITOR_RGB) || ( !aPixels[3] ))
|
||||
{ // "Text optimized" IF this pixel on, and adjacent right pixel off, then colorize first half-pixel of this byte
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y , HGR_BLUE ); // 2000:D5 AA D5
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+0 ,y+1, HGR_BLUE );
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y , HGR_ORANGE ); // 2000: AA D5
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+16,y+1, HGR_ORANGE );
|
||||
{
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+0 ,y , HGR_BLUE ); // 2000:D5 AA D5
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+HIRES_COLUMN_SUBUNIT_SIZE,y , HGR_ORANGE ); // 2000: AA D5
|
||||
}
|
||||
#endif // HALF_PIXEL_BLEED
|
||||
}
|
||||
}
|
||||
#endif // HALF_PIXEL_SOLID
|
||||
}
|
||||
x += hibit;
|
||||
|
||||
while (x < 28)
|
||||
//
|
||||
|
||||
int x = currHighBit;
|
||||
|
||||
for (int odd = 0; odd < 2; odd++) // even then odd sub-units
|
||||
{
|
||||
int adj = (x >= 14) << 1; // Adjust start of 7 last pixels to be 16-byte aligned!
|
||||
int odd = (x >= 14);
|
||||
for (iPixel = 2; iPixel < 9; iPixel++)
|
||||
if (odd)
|
||||
x = HIRES_COLUMN_SUBUNIT_SIZE + currHighBit;
|
||||
|
||||
for (int iPixel = 2; iPixel < 9; iPixel++)
|
||||
{
|
||||
int color = CM_Black;
|
||||
if (aPixels[iPixel]) // pixel on
|
||||
@ -373,115 +312,28 @@ Legend:
|
||||
if (aPixels[iPixel-1] || aPixels[iPixel+1]) // adjacent pixels are always white
|
||||
color = CM_White;
|
||||
else
|
||||
color = ((odd ^ (iPixel&1)) << 1) | hibit; // map raw color to our hi-res colors
|
||||
color = ((odd ^ (iPixel&1)) << 1) | currHighBit; // map raw color to our hi-res colors
|
||||
}
|
||||
#if HALF_PIXEL_SOLID
|
||||
else if (aPixels[iPixel-1] && aPixels[iPixel+1]) // IF prev_pixel && next_pixel THEN
|
||||
{
|
||||
// Activate fringe reduction on white HGR text - drawback: loss of color mix patterns in HGR video mode.
|
||||
if (
|
||||
(videoType == VT_COLOR_MONITOR_RGB) // Fill in colors in between white pixels
|
||||
// || (videoType == VT_COLOR_TVEMU) // Fill in colors in between white pixels (Post Processing will mix/merge colors)
|
||||
|| !(aPixels[iPixel-2] && aPixels[iPixel+2]) ) // VT_COLOR_TEXT_OPTIMIZED -> Don't fill in colors in between white
|
||||
{
|
||||
// Test Pattern: Ultima 4 Logo - Castle
|
||||
// 3AC8: 36 5B 6D 36
|
||||
color = ((odd ^ !(iPixel&1)) << 1) | hibit; // No white HGR text optimization
|
||||
color = ((odd ^ !(iPixel&1)) << 1) | currHighBit; // No white HGR text optimization
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Colors - Top/Bottom Left/Right
|
||||
// cTL cTR
|
||||
// cBL cBR
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+adj ,y ,HiresToPalIndex[color]); // cTL
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+adj+1,y ,HiresToPalIndex[color]); // cTR
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+adj ,y+1,HiresToPalIndex[color]); // cBL
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+adj+1,y+1,HiresToPalIndex[color]); // cBR
|
||||
|
||||
// Each HGR 7M pixel is a left 14M & right 14M DHGR pixel
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x ,y ,HiresToPalIndex[color]); // Color for left 14M pixel
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES+offsetx+x+1,y ,HiresToPalIndex[color]); // Color for right 14M pixel
|
||||
|
||||
x += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void V_CreateLookup_Hires()
|
||||
{
|
||||
// int iMonochrome = GetMonochromeIndex();
|
||||
|
||||
// BYTE colorval[6] = {MAGENTA,BLUE,GREEN,ORANGE,BLACK,WHITE};
|
||||
// BYTE colorval[6] = {HGR_VIOLET,HGR_BLUE,HGR_GREEN,HGR_ORANGE,HGR_BLACK,HGR_WHITE};
|
||||
for (int iColumn = 0; iColumn < 16; iColumn++)
|
||||
{
|
||||
int coloffs = iColumn << 5;
|
||||
|
||||
for (unsigned iByte = 0; iByte < 256; iByte++)
|
||||
{
|
||||
int aPixels[11];
|
||||
|
||||
aPixels[ 0] = iColumn & 4;
|
||||
aPixels[ 1] = iColumn & 8;
|
||||
aPixels[ 9] = iColumn & 1;
|
||||
aPixels[10] = iColumn & 2;
|
||||
|
||||
int nBitMask = 1;
|
||||
int iPixel;
|
||||
for (iPixel = 2; iPixel < 9; iPixel++) {
|
||||
aPixels[iPixel] = ((iByte & nBitMask) != 0);
|
||||
nBitMask <<= 1;
|
||||
}
|
||||
|
||||
int hibit = ((iByte & 0x80) != 0);
|
||||
int x = 0;
|
||||
int y = iByte << 1;
|
||||
|
||||
while (x < 28)
|
||||
{
|
||||
int adj = (x >= 14) << 1;
|
||||
int odd = (x >= 14);
|
||||
|
||||
for (iPixel = 2; iPixel < 9; iPixel++)
|
||||
{
|
||||
int color = CM_Black;
|
||||
if (aPixels[iPixel])
|
||||
{
|
||||
if (aPixels[iPixel-1] || aPixels[iPixel+1])
|
||||
color = CM_White;
|
||||
else
|
||||
color = ((odd ^ (iPixel&1)) << 1) | hibit;
|
||||
}
|
||||
else if (aPixels[iPixel-1] && aPixels[iPixel+1])
|
||||
{
|
||||
// Activate fringe reduction on white HGR text - drawback: loss of color mix patterns in HGR video mode.
|
||||
// VT_COLOR_STANDARD = Fill in colors in between white pixels
|
||||
// VT_COLOR_TVEMU = Fill in colors in between white pixels (Post Processing will mix/merge colors)
|
||||
// VT_COLOR_TEXT_OPTIMIZED --> !(aPixels[iPixel-2] && aPixels[iPixel+2]) = Don't fill in colors in between white
|
||||
if (/*(g_eVideoType == VT_COLOR_TVEMU) ||*/ !(aPixels[iPixel-2] && aPixels[iPixel+2]) )
|
||||
color = ((odd ^ !(iPixel&1)) << 1) | hibit; // No white HGR text optimization
|
||||
}
|
||||
|
||||
//if (g_eVideoType == VT_MONO_AUTHENTIC) {
|
||||
// int nMonoColor = (color != CM_Black) ? iMonochrome : BLACK;
|
||||
// SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj ,y , nMonoColor); // buggy
|
||||
// SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj+1,y , nMonoColor); // buggy
|
||||
// SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj ,y+1,BLACK); // BL
|
||||
// SETSOURCEPIXEL(SRCOFFS_HIRES+coloffs+x+adj+1,y+1,BLACK); // BR
|
||||
//} else
|
||||
{
|
||||
// Colors - Top/Bottom Left/Right
|
||||
// cTL cTR
|
||||
// cBL cBR
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES2+coloffs+x+adj ,y ,HiresToPalIndex[color]); // cTL
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES2+coloffs+x+adj+1,y ,HiresToPalIndex[color]); // cTR
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES2+coloffs+x+adj ,y+1,HiresToPalIndex[color]); // cBL
|
||||
SETSOURCEPIXEL(SRCOFFS_HIRES2+coloffs+x+adj+1,y+1,HiresToPalIndex[color]); // cBR
|
||||
}
|
||||
x += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // even/odd sub-units
|
||||
} // iByte
|
||||
} // iColumn
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@ -492,7 +344,7 @@ const UINT FRAMEBUFFER_W = 560;
|
||||
const UINT FRAMEBUFFER_H = 384;
|
||||
const UINT HGR_MATRIX_YOFFSET = 2;
|
||||
|
||||
static BYTE hgrpixelmatrix[FRAMEBUFFER_W][FRAMEBUFFER_H/2 + 2 * HGR_MATRIX_YOFFSET]; // 2 extra scan lines on bottom?
|
||||
static BYTE hgrpixelmatrix[FRAMEBUFFER_W][FRAMEBUFFER_H/2 + 2 * HGR_MATRIX_YOFFSET]; // 2 extra scan lines on top & bottom
|
||||
static BYTE colormixbuffer[6]; // 6 hires colours
|
||||
static WORD colormixmap[6][6][6]; // top x middle x bottom
|
||||
|
||||
@ -567,11 +419,11 @@ static void CreateColorMixMap(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void MixColorsVertical(int matx, int maty)
|
||||
static void MixColorsVertical(int matx, int maty, bool isSWMIXED)
|
||||
{
|
||||
int bot1idx, bot2idx;
|
||||
|
||||
if (VideoGetSWMIXED() && maty > 159)
|
||||
if (isSWMIXED && maty > 159)
|
||||
{
|
||||
if (maty < 161)
|
||||
{
|
||||
@ -608,45 +460,46 @@ static void MixColorsVertical(int matx, int maty)
|
||||
colormixbuffer[5] = (twoHalfPixel & 0x00FF);
|
||||
}
|
||||
|
||||
static void CopyMixedSource(int x, int y, int sourcex, int sourcey, bgra_t *pVideoAddress)
|
||||
static void CopyMixedSource(int x, int y, int sx, int sy, bgra_t *pVideoAddress)
|
||||
{
|
||||
const BYTE* const currsourceptr = g_aSourceStartofLine[sourcey]+sourcex;
|
||||
UINT32* const currdestptr = (UINT32*) pVideoAddress;
|
||||
const BYTE* const pSrc = g_aSourceStartofLine[ sy ] + sx;
|
||||
|
||||
const int matx = x*2;
|
||||
const int matx = x*14;
|
||||
const int maty = HGR_MATRIX_YOFFSET + y;
|
||||
const int hgrlinesabove = (y > 0) ? 1 : 0;
|
||||
const int hgrlinesbelow = VideoGetSWMIXED() ? ((y < 159)? 1:0) : ((y < 191)? 1:0);
|
||||
const int istart = 2 - (hgrlinesabove*2);
|
||||
const int iend = 3 + (hgrlinesbelow*2);
|
||||
const bool isSWMIXED = VideoGetSWMIXED();
|
||||
|
||||
// transfer 14 pixels (i.e. the visible part of an apple hgr-byte) from row to pixelmatrix
|
||||
for (int count = 0, bufxoffset = 0; count < 14; count++, bufxoffset += 1)
|
||||
for (int nBytes=13; nBytes>=0; nBytes--)
|
||||
{
|
||||
hgrpixelmatrix[matx+count][maty] = *(currsourceptr+bufxoffset);
|
||||
hgrpixelmatrix[matx+nBytes][maty] = *(pSrc+nBytes);
|
||||
}
|
||||
|
||||
const bool bIsHalfScanLines = IsVideoStyle(VS_HALF_SCANLINES);
|
||||
const UINT frameBufferWidth = GetFrameBufferWidth();
|
||||
|
||||
for (int nBytes=13; nBytes>=0; nBytes--)
|
||||
{
|
||||
// color mixing between adjacent scanlines at current x position
|
||||
MixColorsVertical(matx+count, maty);
|
||||
MixColorsVertical(matx+nBytes, maty, isSWMIXED); //Post: colormixbuffer[]
|
||||
|
||||
// transfer up to 6 mixed (half-)pixels of current column to framebuffer
|
||||
UINT32* currptr = currdestptr+bufxoffset;
|
||||
if (hgrlinesabove)
|
||||
currptr += GetFrameBufferWidth() * 2;
|
||||
UINT32* pDst = (UINT32*) pVideoAddress;
|
||||
|
||||
for (int i = istart; i <= iend; currptr -= GetFrameBufferWidth(), i++)
|
||||
for (int h=HGR_MATRIX_YOFFSET; h<=HGR_MATRIX_YOFFSET+1; h++)
|
||||
{
|
||||
if (IsVideoStyle(VS_HALF_SCANLINES) && (i & 1))
|
||||
if (bIsHalfScanLines && (h & 1))
|
||||
{
|
||||
// 50% Half Scan Line clears every odd scanline (and SHIFT+PrintScreen saves only the even rows)
|
||||
*currptr = 0;
|
||||
*(pDst+nBytes) = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ASSERT( colormixbuffer[i] < (sizeof(PalIndex2RGB)/sizeof(PalIndex2RGB[0])) );
|
||||
const RGBQUAD& rRGB = PalIndex2RGB[ colormixbuffer[i] ];
|
||||
_ASSERT( colormixbuffer[h] < (sizeof(PalIndex2RGB)/sizeof(PalIndex2RGB[0])) );
|
||||
const RGBQUAD& rRGB = PalIndex2RGB[ colormixbuffer[h] ];
|
||||
const UINT32 rgb = (((UINT32)rRGB.rgbRed)<<16) | (((UINT32)rRGB.rgbGreen)<<8) | ((UINT32)rRGB.rgbBlue);
|
||||
*currptr = rgb;
|
||||
*(pDst+nBytes) = rgb;
|
||||
}
|
||||
|
||||
pDst -= frameBufferWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -657,12 +510,11 @@ static void CopyMixedSource(int x, int y, int sourcex, int sourcey, bgra_t *pVid
|
||||
static void CopySource(int w, int h, int sx, int sy, bgra_t *pVideoAddress, const int nSrcAdjustment = 0)
|
||||
{
|
||||
UINT32* pDst = (UINT32*) pVideoAddress;
|
||||
LPBYTE pSrc = g_aSourceStartofLine[ sy ] + sx;
|
||||
int nBytes;
|
||||
const BYTE* const pSrc = g_aSourceStartofLine[ sy ] + sx;
|
||||
|
||||
while (h--)
|
||||
{
|
||||
nBytes = w;
|
||||
int nBytes = w;
|
||||
while (nBytes)
|
||||
{
|
||||
--nBytes;
|
||||
@ -682,12 +534,13 @@ static void CopySource(int w, int h, int sx, int sy, bgra_t *pVideoAddress, cons
|
||||
}
|
||||
|
||||
pDst -= GetFrameBufferWidth();
|
||||
pSrc -= SRCOFFS_TOTAL;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#define HIRES_COLUMN_OFFSET (((byteval1 & 0xE0) << 2) | ((byteval3 & 0x03) << 5)) // (prevHighBit | last 2 pixels | next 2 pixesl) * HIRES_COLUMN_UNIT_SIZE
|
||||
|
||||
void UpdateHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
{
|
||||
uint8_t *pMain = MemGetMainPtr(addr);
|
||||
@ -695,21 +548,14 @@ void UpdateHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
BYTE byteval2 = *(pMain);
|
||||
BYTE byteval3 = (x < 39) ? *(pMain+1) : 0;
|
||||
|
||||
#define COLOFFS (((byteval1 & 0x60) << 2) | ((byteval3 & 0x03) << 5))
|
||||
if (IsVideoStyle(VS_COLOR_VERTICAL_BLEND))
|
||||
{
|
||||
CopyMixedSource(
|
||||
x*7, y,
|
||||
// SRCOFFS_HIRES2+COLOFFS+((x & 1) << 4), (((int)byteval2) << 1),
|
||||
SRCOFFS_HIRES+COLOFFS+((x & 1) << 4), (((int)byteval2) << 1),
|
||||
pVideoAddress
|
||||
);
|
||||
CopyMixedSource(x, y, SRCOFFS_HIRES+HIRES_COLUMN_OFFSET+((x & 1)*HIRES_COLUMN_SUBUNIT_SIZE), (int)byteval2, pVideoAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopySource(14,2, SRCOFFS_HIRES+COLOFFS+((x & 1) << 4), (((int)byteval2) << 1), pVideoAddress);
|
||||
CopySource(14,2, SRCOFFS_HIRES+HIRES_COLUMN_OFFSET+((x & 1)*HIRES_COLUMN_SUBUNIT_SIZE), (int)byteval2, pVideoAddress);
|
||||
}
|
||||
#undef COLOFFS
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@ -735,7 +581,7 @@ void UpdateDHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress, bool
|
||||
#define PIXEL 0
|
||||
if (updateAux)
|
||||
{
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE)<<1, pVideoAddress);
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
pVideoAddress += 7;
|
||||
}
|
||||
#undef PIXEL
|
||||
@ -743,7 +589,7 @@ void UpdateDHiResCell (int x, int y, uint16_t addr, bgra_t *pVideoAddress, bool
|
||||
#define PIXEL 7
|
||||
if (updateMain)
|
||||
{
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE)<<1, pVideoAddress);
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
}
|
||||
#undef PIXEL
|
||||
}
|
||||
@ -767,12 +613,12 @@ int UpdateDHiRes160Cell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
dwordval <<= 2;
|
||||
|
||||
#define PIXEL 0
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE)<<1, pVideoAddress, 1);
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress, 1);
|
||||
pVideoAddress += 7;
|
||||
#undef PIXEL
|
||||
|
||||
#define PIXEL 8
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE)<<1, pVideoAddress, 1);
|
||||
CopySource(7,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress, 1);
|
||||
#undef PIXEL
|
||||
|
||||
return 7*2;
|
||||
@ -798,12 +644,12 @@ int UpdateDHiRes160Cell (int x, int y, uint16_t addr, bgra_t *pVideoAddress)
|
||||
dwordval <<= 2;
|
||||
|
||||
#define PIXEL 0
|
||||
CopySource(8,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE)<<1, pVideoAddress);
|
||||
CopySource(8,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
pVideoAddress += 8;
|
||||
#undef PIXEL
|
||||
|
||||
#define PIXEL 8
|
||||
CopySource(8,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE)<<1, pVideoAddress);
|
||||
CopySource(8,2, SRCOFFS_DHIRES+10*HIBYTE(VALUE)+COLOR, LOBYTE(VALUE), pVideoAddress);
|
||||
#undef PIXEL
|
||||
|
||||
return 8*2;
|
||||
@ -866,10 +712,9 @@ static void V_CreateDIBSections(void)
|
||||
g_aSourceStartofLine[ y ] = g_pSourcePixels + SRCOFFS_TOTAL*((MAX_SOURCE_Y-1) - y);
|
||||
|
||||
// DRAW THE SOURCE IMAGE INTO THE SOURCE BIT BUFFER
|
||||
ZeroMemory(g_pSourcePixels, SRCOFFS_TOTAL*MAX_SOURCE_Y); // 32 bytes/pixel * 16 colors = 512 bytes/row
|
||||
ZeroMemory(g_pSourcePixels, SRCOFFS_TOTAL*MAX_SOURCE_Y);
|
||||
|
||||
V_CreateLookup_Lores();
|
||||
// V_CreateLookup_Hires(); // For CopyMixedSource() / VS_COLOR_VERTICAL_BLEND, 280-pixel (from 1.25)
|
||||
V_CreateLookup_HiResHalfPixel_Authentic(VT_COLOR_MONITOR_RGB);
|
||||
V_CreateLookup_DoubleHires();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user