Appalm/src/video.c
2019-04-21 06:53:32 -07:00

1154 lines
34 KiB
C
Executable File

#include <PalmOS.h>
#include "Apple2.h"
extern READBYTE *ReadFunction;
extern WRITEBYTE *WriteFunction;
extern UInt8 *AppleMemory;
extern UInt8 *AuxMemory;
extern UInt8 *AppleROM;
extern UInt16 grMode;
extern char *AppleFontBitmap7x8;
extern char *AppleFontBitmap4x6;
void READONLY(UInt16, UInt8);
UInt8 RRMP(UInt16);
#define VIDIMAGE_TEXT 0
#define VIDIMAGE_LORES_MIX 1
#define VIDIMAGE_LORES 2
#define VIDIMAGE_HIRES_MIX 3
#define VIDIMAGE_HIRES 4
#define VIDIMAGE_DBLTEXT 5
VIDIMAGE vidUpdateFuncs[6];
VIDIMAGE updateVideo;
void gryUpdateText(void);
void gryUpdateHires(void);
void gryUpdateHiresMixed(void);
void clrUpdateText(void);
void clrUpdateHires(void);
void clrUpdateHiresMixed(void);
void hrclrUpdateText(void);
void hrclrUpdateLores(void);
void hrclrUpdateLoresMixed(void);
void hrclrUpdateHires(void);
void hrclrUpdateHiresMixed(void);
void hrclrUpdateDblText(void);
/*
* Variables needed to update the video image.
*/
UInt8 dirtyVideo;
UInt8 *AppleFont = 0;
UInt8 *vidImage; // Destination image bitmap (screen)
UInt16 vidPageOffset; // Source apple memory offset
UInt16 ScanlineOffsetTable[192];
UInt8 HRMono[256];
UInt8 *HRMonoLo, *HRMonoHi;
/*
* Use a direct copy of the screen.
*/
UInt8 *vidScreenCache = 0;
#define VID_CACHE_OFFSET(v) ScanlineOffsetTable[v]
#define VID_CACHE_INVALIDATE MemSet(vidScreenCache, 0x2000, 0x69)
void initVideo(void)
{
WinHandle onScreen;
BitmapType *scanline;
UInt16 i, count;
dirtyVideo = true;
onScreen = WinGetDisplayWindow();
scanline = WinGetBitmap(onScreen);
vidImage = (UInt8*) BmpGetBits(scanline);
if (!vidScreenCache)
vidScreenCache = MemPtrNew(0x2000);
if (grMode > GRMODE_COLOR)
{
vidImage += (GRMODE_ISCOLOR(grMode) ? 320 : 40) * 30;
if (!AppleFont)
AppleFont = MemPtrNew(0x100 * 0x08);
MemMove(AppleFont, AppleFontBitmap7x8, 0x40 * 0x08);
MemMove(AppleFont + 0x40 * 0x08, AppleFontBitmap7x8, 0x40 * 0x08);
MemMove(AppleFont + 0x40 * 0x08 * 2, AppleFontBitmap7x8, 0x40 * 0x08);
MemMove(AppleFont + 0x40 * 0x08 * 3, AppleFontBitmap7x8, 0x20 * 0x08);
MemMove(AppleFont + 0x40 * 0x08 * 3 + 0x20 * 0x08, AppleFontBitmap7x8 + 0x40 * 0x08, 0x20 * 0x08);
for (count = 0x80 * 0x08; count < (0x100 * 0x08); count++) AppleFont[count] = ~AppleFont[count];
vidUpdateFuncs[VIDIMAGE_TEXT] = hrclrUpdateText;
vidUpdateFuncs[VIDIMAGE_LORES] = hrclrUpdateLores;
vidUpdateFuncs[VIDIMAGE_LORES_MIX] = hrclrUpdateLoresMixed;
vidUpdateFuncs[VIDIMAGE_HIRES] = hrclrUpdateHires;
vidUpdateFuncs[VIDIMAGE_HIRES_MIX] = hrclrUpdateHiresMixed;
vidUpdateFuncs[VIDIMAGE_DBLTEXT] = hrclrUpdateDblText;
}
else
{
if (!AppleFont)
AppleFont = MemPtrNew(0x100 * 0x06);
MemMove(AppleFont, AppleFontBitmap4x6, 0x40 * 0x06);
MemMove(AppleFont + 0x40 * 0x06, AppleFontBitmap4x6, 0x40 * 0x06);
MemMove(AppleFont + 0x40 * 0x06 * 2, AppleFontBitmap4x6, 0x40 * 0x06);
MemMove(AppleFont + 0x40 * 0x06 * 3, AppleFontBitmap4x6, 0x20 * 0x06);
MemMove(AppleFont + 0x40 * 0x06 * 3 + 0x20 * 0x06, AppleFontBitmap4x6 + 0x40 * 0x06, 0x20 * 0x06);
if (grMode == GRMODE_COLOR)
{
vidImage += 160 * 15;
/*
* Invert font data.
*/
for (count = 0x80 * 0x06; count < (0x100 * 0x06); count++)
AppleFont[count] = ~AppleFont[count];
vidUpdateFuncs[VIDIMAGE_TEXT] = clrUpdateText;
vidUpdateFuncs[VIDIMAGE_LORES_MIX] = clrUpdateText;
vidUpdateFuncs[VIDIMAGE_LORES] = clrUpdateText;
vidUpdateFuncs[VIDIMAGE_HIRES] = clrUpdateHires;
vidUpdateFuncs[VIDIMAGE_HIRES_MIX] = clrUpdateHiresMixed;
vidUpdateFuncs[VIDIMAGE_DBLTEXT] = clrUpdateText;
}
else
{
vidImage += 40 * 15;
/*
* Expand font data.
*/
for (count = 0x80 * 0x06; count < (0x100 * 0x06); count++)
{
AppleFont[count] = (((AppleFont[count] & 0x01) ? 0x00 : 0x03)
| ((AppleFont[count] & 0x02) ? 0x00 : 0x0C)
| ((AppleFont[count] & 0x04) ? 0x00 : 0x30)
| ((AppleFont[count] & 0x08) ? 0x00 : 0xC0));
}
/*
* Create Hires->Mono conversion table.
*/
HRMonoLo = HRMono;
HRMonoHi = HRMono + 128;
for (count = 0; count < 0x80; count++)
{
HRMonoLo[count] = ((count & 0x40 ? 0 : 0x02)
| (count & 0x20 ? 0 : 0x04)
| (count & 0x10 ? 0 : 0x08)
| (count & 0x08 ? 0 : 0x10)
| (count & 0x04 ? 0 : 0x20)
| (count & 0x02 ? 0 : 0x40)
| (count & 0x01 ? 0 : 0x80));
HRMonoHi[count] = ((count & 0x40 ? 0 : 0x01)
| (count & 0x20 ? 0 : 0x02)
| (count & 0x10 ? 0 : 0x04)
| (count & 0x08 ? 0 : 0x08)
| (count & 0x04 ? 0 : 0x10)
| (count & 0x02 ? 0 : 0x20)
| (count & 0x01 ? 0 : 0x40));
}
vidUpdateFuncs[VIDIMAGE_TEXT] = gryUpdateText;
vidUpdateFuncs[VIDIMAGE_LORES_MIX] = gryUpdateText;
vidUpdateFuncs[VIDIMAGE_LORES] = gryUpdateText;
vidUpdateFuncs[VIDIMAGE_HIRES] = gryUpdateHires;
vidUpdateFuncs[VIDIMAGE_HIRES_MIX] = gryUpdateHiresMixed;
vidUpdateFuncs[VIDIMAGE_DBLTEXT] = gryUpdateText;
}
}
/*
* Create offset table for rendering video image top->down.
*/
for (i = 0;i < 192;i++)
ScanlineOffsetTable[i] = (i & 7) * 0x400 + ((i >> 3) & 7) * 0x80 + (i >> 6) * 0x28;
setVideoFuncs(true);
}
/****************************************************************\
* *
* Video mode state *
* *
\****************************************************************/
void clrVidFuncs(UInt16 vidBits)
{
UInt16 page;
if (!SS_ISSET(vidBits, SS_TEXT) && SS_ISSET(vidBits, SS_HIRES))
{
if (SS_ISSET(vidBits, SS_PAGE2))
for (page = 0x40; page < 0x60; page++)
WriteFunction[page] = NULL;
else
for (page = 0x20; page < 0x40; page++)
WriteFunction[page] = NULL;
}
else
{
if (SS_ISSET(vidBits, SS_PAGE2) && !SS_ISSET(vidBits, SS_80STORE))
{
WriteFunction[0x08] = NULL;
WriteFunction[0x09] = NULL;
WriteFunction[0x0A] = NULL;
WriteFunction[0x0B] = NULL;
}
else
{
WriteFunction[0x04] = NULL;
WriteFunction[0x05] = NULL;
WriteFunction[0x06] = NULL;
WriteFunction[0x07] = NULL;
ReadFunction[0x04] = NULL;
ReadFunction[0x05] = NULL;
ReadFunction[0x06] = NULL;
ReadFunction[0x07] = NULL;
}
}
}
/* Screen Write */
void WTXTM(UInt16, UInt8);
void WATXTM(UInt16, UInt8);
UInt8 RATXTM(UInt16 address);
void awrap_AuxTxtMemReadWrite(void)
{
asm(".global WTXTM");
asm(".global WATXTM");
asm(".global RATXTM");
asm("WTXTM:");
asm("move.b %d0, (%a2,%d6.l)");
asm("move.b #1, dirtyVideo@END.w(%a5)");
asm("rts");
asm("WATXTM:");
asm("move.l AuxMemory@END.w(%a5), %a6");
asm("add.l #(16384-0x400), %a6");
asm("move.b %d0, (%a6, %d6.l)");
asm("move.b #1, dirtyVideo@END.w(%a5)");
asm("rts");
asm("RATXTM:");
asm("move.l AuxMemory@END.w(%a5), %a6");
asm("add.l #(16384-0x400), %a6");
asm("clr.l %d0");
asm("move.b (%a6, %d6.l), %d0");
asm("rts");
}
WRMEM_CWRAP(WSCM, address, data)
{
UInt16 page;
dirtyVideo = 2; // Add call to setVideoFuncs at next VideoUpdate
AppleMemory[address] = data;
/*
* Once dirtyVideo is set, no need to slow down the rest.
*/
clrVidFuncs(vidIOU);
}
/*
* Set the updateVideo function based on all the settings.
* This is incomplete - missing lo-res checking.
*/
void setVideoFuncs(Boolean invalidate_cache)
{
UInt16 page;
if (invalidate_cache)
{
VID_CACHE_INVALIDATE;
}
if (!SS_ISSET(memIOU, SS_RAMWRT))
{
if (SS_ISSET(vidIOU, SS_TEXT))
{
updateVideo = vidUpdateFuncs[SS_ISSET(vidIOU, SS_80VID) ? VIDIMAGE_DBLTEXT : VIDIMAGE_TEXT];
if (SS_ISSET(vidIOU, SS_PAGE2))
{
if (SS_ISSET(vidIOU, SS_80STORE))
{
vidPageOffset = 0x0400;
if ((grMode > GRMODE_COLOR) && prefs.enable80Col)
{
WriteFunction[0x04] = WATXTM;
WriteFunction[0x05] = WATXTM;
WriteFunction[0x06] = WATXTM;
WriteFunction[0x07] = WATXTM;
ReadFunction[0x04] = RATXTM;
ReadFunction[0x05] = RATXTM;
ReadFunction[0x06] = RATXTM;
ReadFunction[0x07] = RATXTM;
}
else
{
WriteFunction[0x04] = READONLY;
WriteFunction[0x05] = READONLY;
WriteFunction[0x06] = READONLY;
WriteFunction[0x07] = READONLY;
}
}
else
{
vidPageOffset = 0x0800;
WriteFunction[0x08] = WTXTM;
WriteFunction[0x09] = WTXTM;
WriteFunction[0x0A] = WTXTM;
WriteFunction[0x0B] = WTXTM;
}
}
else
{
vidPageOffset = 0x0400;
WriteFunction[0x04] = WTXTM;
WriteFunction[0x05] = WTXTM;
WriteFunction[0x06] = WTXTM;
WriteFunction[0x07] = WTXTM;
}
}
else if (SS_ISSET(vidIOU, SS_HIRES))
{
if (SS_ISSET(vidIOU, SS_PAGE2))
{
vidPageOffset = 0x4000;
for (page = 0x40; page < 0x60; page++)
WriteFunction[page] = WSCM;
if (SS_ISSET(vidIOU, SS_MIXED))
{
updateVideo = vidUpdateFuncs[VIDIMAGE_HIRES_MIX];
WriteFunction[0x04] = NULL;
WriteFunction[0x05] = NULL;
WriteFunction[0x06] = NULL;
WriteFunction[0x07] = NULL;
WriteFunction[0x08] = WSCM;
WriteFunction[0x09] = WSCM;
WriteFunction[0x0A] = WSCM;
WriteFunction[0x0B] = WSCM;
}
else
updateVideo = vidUpdateFuncs[VIDIMAGE_HIRES];
}
else
{
vidPageOffset = 0x2000;
for (page = 0x20; page < 0x40; page++)
WriteFunction[page] = WSCM;
if (SS_ISSET(vidIOU, SS_MIXED))
{
updateVideo = vidUpdateFuncs[VIDIMAGE_HIRES_MIX];
WriteFunction[0x04] = WSCM;
WriteFunction[0x05] = WSCM;
WriteFunction[0x06] = WSCM;
WriteFunction[0x07] = WSCM;
WriteFunction[0x08] = NULL;
WriteFunction[0x09] = NULL;
WriteFunction[0x0A] = NULL;
WriteFunction[0x0B] = NULL;
}
else
updateVideo = vidUpdateFuncs[VIDIMAGE_HIRES];
}
}
else
{
if (SS_ISSET(vidIOU, SS_PAGE2))
{
vidPageOffset = 0x0800;
updateVideo = SS_ISSET(vidIOU, SS_MIXED) ? vidUpdateFuncs[VIDIMAGE_LORES_MIX] : vidUpdateFuncs[VIDIMAGE_LORES];
WriteFunction[0x08] = WSCM;
WriteFunction[0x09] = WSCM;
WriteFunction[0x0A] = WSCM;
WriteFunction[0x0B] = WSCM;
}
else
{
vidPageOffset = 0x0400;
updateVideo = SS_ISSET(vidIOU, SS_MIXED) ? vidUpdateFuncs[VIDIMAGE_LORES_MIX] : vidUpdateFuncs[VIDIMAGE_LORES];
WriteFunction[0x04] = WSCM;
WriteFunction[0x05] = WSCM;
WriteFunction[0x06] = WSCM;
WriteFunction[0x07] = WSCM;
}
}
}
}
void toggleVideoSoftSwitch(UInt8 io)
{
UInt16 dirty, page;
Boolean invalidate = false;
dirty = vidIOU;
switch (io)
{
case 0x00: // Text -> Graphics
if (SS_ISSET(vidIOU, SS_TEXT))
invalidate = true;
SS_RESET(vidIOU, SS_TEXT);
break;
case 0x01: // Graphics -> Text
if (!SS_ISSET(vidIOU, SS_TEXT))
invalidate = true;
SS_SET(vidIOU, SS_TEXT);
break;
case 0x02: // Full Screen
if (SS_ISSET(vidIOU, SS_MIXED))
invalidate = true;
SS_RESET(vidIOU, SS_MIXED);
break;
case 0x03: // Mixed Screen
if (!SS_ISSET(vidIOU, SS_MIXED))
invalidate = true;
SS_SET(vidIOU, SS_MIXED);
break;
case 0x04: // page 1
SS_RESET(vidIOU, SS_PAGE2);
break;
case 0x05: // page 2
SS_SET(vidIOU, SS_PAGE2);
break;
case 0x06: // HiRes -> Text/LoRes
if (SS_ISSET(vidIOU, SS_HIRES))
invalidate = true;
SS_RESET(vidIOU, SS_HIRES);
break;
case 0x07: // Text/LoRes -> HiRes
if (!SS_ISSET(vidIOU, SS_HIRES))
invalidate = true;
SS_SET(vidIOU, SS_HIRES);
break;
}
if (dirty != vidIOU)
{
dirtyVideo = true;
clrVidFuncs(dirty);
setVideoFuncs(invalidate);
if (!SS_ISSET(vidIOU, SS_TEXT) && SS_ISSET((dirty ^ vidIOU), SS_PAGE2))
{
AppleInstrCount += AppleInstrInc - state6502.LongRegs.INST;
state6502.LongRegs.INST = 0; // Keep frequent screen updates from holding off user input.
}
}
}
/****************************************************************\
* *
* Video update routines *
* *
\****************************************************************/
#define PALM_CLR_WHITE 0
#define PALM_CLR_BLACK 255
#define PALM_CLR_GREEN 210
#define PALM_CLR_VIOLET 17
#define PALM_CLR_PURPLE 17
#define PALM_CLR_RED 125
#define PALM_CLR_BLUE 107
#define PALM_CLR_DRKRED (8*16+9)
#define PALM_CLR_DRKBLUE (12*16+11)
#define PALM_CLR_DRKGREEN (13*16+4)
#define PALM_CLR_DRKGREY (13*16+11)
#define PALM_CLR_CYAN (4*16+4)
#define PALM_CLR_BROWN (8*16+7)
#define PALM_CLR_ORANGE (7*16+5)
#define PALM_CLR_LTGREY (13*16+14)
#define PALM_CLR_PINK 2
#define PALM_CLR_YELLOW 108
#define PALM_CLR_AQUA (5*16+10)
#define PALM_CLR_GREY (13*16+12)
/*
* 16 color table.
*/
UInt8 clr16[16] =
{
PALM_CLR_BLACK,
PALM_CLR_DRKRED,
PALM_CLR_DRKBLUE,
PALM_CLR_VIOLET,
PALM_CLR_DRKGREEN,
PALM_CLR_DRKGREY,
PALM_CLR_BLUE,
PALM_CLR_CYAN,
PALM_CLR_BROWN,
PALM_CLR_ORANGE,
PALM_CLR_LTGREY,
PALM_CLR_PINK,
PALM_CLR_GREEN,
PALM_CLR_YELLOW,
PALM_CLR_AQUA,
PALM_CLR_WHITE
};
/*
* Color array for standard res device.
*/
UInt8 pixEven[96] =
{
/*
* 0 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_VIOLET,
PALM_CLR_GREY,
PALM_CLR_GREEN ,
PALM_CLR_GREEN ,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_VIOLET,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* 1 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_BLUE ,
PALM_CLR_GREY,
PALM_CLR_RED ,
PALM_CLR_RED ,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_BLUE ,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* These values are for the even->odd byte transition.
* Even 0 MSB -> Odd 0 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_VIOLET,
PALM_CLR_GREY,
PALM_CLR_GREEN ,
PALM_CLR_GREEN ,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_VIOLET,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* These values are for the even->odd byte transition.
* Even 1 MSB -> Odd 0 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_BLUE ,
PALM_CLR_GREY,
PALM_CLR_GREEN ,
PALM_CLR_GREEN ,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_BLUE ,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* These values are for the even->odd byte transition.
* Even 0 MSB -> Odd 1 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_VIOLET,
PALM_CLR_GREY,
PALM_CLR_RED ,
PALM_CLR_RED ,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_VIOLET,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* These values are for the even->odd byte transition.
* Even 1 MSB -> Odd 1 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_BLUE ,
PALM_CLR_GREY,
PALM_CLR_RED ,
PALM_CLR_RED ,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_BLUE ,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE
};
UInt8 pixOdd[96] =
{
/*
* 0 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_GREEN ,
PALM_CLR_GREY,
PALM_CLR_VIOLET,
PALM_CLR_VIOLET,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_GREEN ,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* 1 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_RED ,
PALM_CLR_GREY,
PALM_CLR_BLUE ,
PALM_CLR_BLUE ,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_RED ,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* These values are for the even->odd byte transition.
* Odd 0 MSB -> Even 0 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_GREEN ,
PALM_CLR_GREY,
PALM_CLR_VIOLET,
PALM_CLR_VIOLET,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_GREEN ,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* These values are for the even->odd byte transition.
* Odd 1 MSB -> Even 0 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_RED ,
PALM_CLR_GREY,
PALM_CLR_VIOLET,
PALM_CLR_VIOLET,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_RED ,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* These values are for the even->odd byte transition.
* Odd 0 MSB -> Even 1 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_GREEN ,
PALM_CLR_GREY,
PALM_CLR_BLUE ,
PALM_CLR_BLUE ,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_GREEN ,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
/*
* These values are for the even->odd byte transition.
* Odd 1 MSB -> Even 1 MSB.
*/
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_RED ,
PALM_CLR_GREY,
PALM_CLR_BLUE ,
PALM_CLR_BLUE ,
PALM_CLR_WHITE ,
PALM_CLR_WHITE ,
PALM_CLR_BLACK ,
PALM_CLR_BLACK ,
PALM_CLR_RED ,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_GREY,
PALM_CLR_WHITE ,
PALM_CLR_WHITE
};
/*
* Color interpolation arrays.
*/
#define CLR_PAIR(c1,c2) (((PALM_CLR_##c1)<<8)|(PALM_CLR_##c2))
/*
* Interpolated colors (sold fill).
*/
UInt16 pixPairEven[96] =
{
/*
* 0 MSB.
*/
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(GREEN , GREEN ),
CLR_PAIR(GREEN , GREEN ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
/*
* 1 MSB.
*/
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(RED , RED ),
CLR_PAIR(RED , RED ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
/*
* These values are for the even->odd byte transition.
* Even 0 MSB -> Odd 0 MSB.
*/
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(GREEN , GREEN ),
CLR_PAIR(GREEN , GREEN ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
/*
* These values are for the even->odd byte transition.
* Even 1 MSB -> Odd 0 MSB.
*/
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(WHITE , BLACK),
CLR_PAIR(GREEN , GREEN),
CLR_PAIR(GREEN , GREEN),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLUE, BLUE ),
CLR_PAIR(WHITE , BLACK),
CLR_PAIR(BLACK , WHITE),
CLR_PAIR(BLACK , WHITE),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(WHITE , WHITE),
/*
* These values are for the even->odd byte transition.
* Even 0 MSB -> Odd 1 MSB.
*/
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(RED , RED ),
CLR_PAIR(RED , RED ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
/*
* These values are for the even->odd byte transition.
* Even 1 MSB -> Odd 1 MSB.
*/
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(WHITE , BLACK),
CLR_PAIR(RED , RED ),
CLR_PAIR(RED , RED ),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(WHITE , BLACK),
CLR_PAIR(BLACK , WHITE),
CLR_PAIR(BLACK , WHITE),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(WHITE , WHITE)
};
UInt16 pixPairOdd[96] =
{
/*
* 0 MSB.
*/
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(GREEN , GREEN ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(GREEN , GREEN ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
/*
* 1 MSB.
*/
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(RED , RED ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(RED , RED ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
/*
* These values are for the even->odd byte transition.
* Odd 0 MSB -> Even 0 MSB.
*/
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(GREEN, GREEN ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(GREEN , GREEN ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
/*
* These values are for the even->odd byte transition.
* Odd 1 MSB -> Even 0 MSB.
*/
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(RED , RED ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(VIOLET, VIOLET),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(BLACK , BLACK ),
CLR_PAIR(RED , RED ),
CLR_PAIR(WHITE , BLACK ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(BLACK , WHITE ),
CLR_PAIR(WHITE , WHITE ),
CLR_PAIR(WHITE , WHITE ),
/*
* These values are for the even->odd byte transition.
* Odd 0 MSB -> Even 1 MSB.
*/
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(GREEN , GREEN),
CLR_PAIR(WHITE , BLACK),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(GREEN , GREEN),
CLR_PAIR(WHITE , BLACK),
CLR_PAIR(BLACK , WHITE),
CLR_PAIR(BLACK , WHITE),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(WHITE , WHITE),
/*
* These values are for the even->odd byte transition.
* Odd 1 MSB -> Even 1 MSB.
*/
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(RED , RED ),
CLR_PAIR(WHITE , BLACK),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(BLUE , BLUE ),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(BLACK , BLACK),
CLR_PAIR(RED , RED ),
CLR_PAIR(WHITE , BLACK),
CLR_PAIR(BLACK , WHITE),
CLR_PAIR(BLACK , WHITE),
CLR_PAIR(WHITE , WHITE),
CLR_PAIR(WHITE , WHITE)
};
typedef void (*pfnVidUpdateSection)(UInt8 *, UInt8 *, UInt8 *);
void gryUpdateTextRow(UInt8 *, UInt8 *, UInt8 *);
void clrUpdateTextRow(UInt8 *, UInt8 *, UInt8 *);
void gryUpdateHiresScanline(UInt8 *, UInt8 *, UInt8 *);
void clrUpdateHiresScanline(UInt8 *, UInt8 *, UInt8 *);
void defUpdateText(pfnVidUpdateSection pfnText, UInt16 pitch)
{
Int16 vert;
UInt8 *_pointer = vidImage;
dirtyVideo = false;
for (vert = 0; vert < 192; vert += 8)
{
pfnText(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += pitch * 6;
}
}
void gryUpdateText(void)
{
defUpdateText(gryUpdateTextRow, 40);
}
void clrUpdateText(void)
{
defUpdateText(clrUpdateTextRow, 160);
}
void defUpdateHires(pfnVidUpdateSection pfnHires, UInt16 pitch)
{
Int16 hori, vert;
UInt16 biteven, bitodd;
UInt8 *_pointer = vidImage;
dirtyVideo = false;
for (vert = 0; vert < 192; vert++)
{
if ((vert & 0x03) == 0x01)
{
UInt32 shrinkScans[10], *scanptr, *nextscanptr;
scanptr = (UInt32 *)&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset];
nextscanptr = (UInt32 *)&AppleMemory[ScanlineOffsetTable[++vert] + vidPageOffset];
for (hori = 0; hori < 10; hori++)
shrinkScans[hori] = *scanptr++ | *nextscanptr++;
pfnHires((UInt8 *)&shrinkScans, _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
}
else
{
pfnHires(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
}
_pointer += pitch;
}
}
void gryUpdateHires(void)
{
defUpdateHires(gryUpdateHiresScanline, 40);
}
void clrUpdateHires(void)
{
defUpdateHires(clrUpdateHiresScanline, 160);
}
void defUpdateHiresMixed(pfnVidUpdateSection pfnHires, pfnVidUpdateSection pfnText, UInt16 pitch)
{
Int16 hori, vert, textpage;
UInt16 scanaddr, chary, biteven, bitodd;
UInt8 *_pointer = vidImage;
dirtyVideo = false;
for (vert = 0; vert < 160/*144*/; vert++)
{
if ((vert & 0x03) == 0x01)
{
UInt32 shrinkScans[10], *scanptr, *nextscanptr;
scanptr = (UInt32 *)&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset];
nextscanptr = (UInt32 *)&AppleMemory[ScanlineOffsetTable[++vert] + vidPageOffset];
for (hori = 0; hori < 10; hori++)
shrinkScans[hori] = *scanptr++ | *nextscanptr++;
pfnHires((UInt8 *)&shrinkScans, _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
}
else
{
pfnHires(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
}
_pointer += pitch;
}
chary = 0;
textpage = SS_ISSET(vidIOU, SS_PAGE2) ? 0x0800 : 0x0400;
while (vert < 192/*144*/)
{
pfnText(&AppleMemory[ScanlineOffsetTable[vert] + textpage], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += pitch * 6;
vert += 8;
}
}
void gryUpdateHiresMixed(void)
{
defUpdateHiresMixed(gryUpdateHiresScanline, gryUpdateTextRow, 40);
}
void clrUpdateHiresMixed(void)
{
defUpdateHiresMixed(clrUpdateHiresScanline, clrUpdateTextRow, 160);
}
void hrclrUpdateTextRow(UInt8 *, UInt8 *, UInt8 *);
void hrclrUpdateText(void)
{
Int16 vert;
UInt8 *_pointer = vidImage;
dirtyVideo = false;
for (vert = 0; vert < 192; vert += 8)
{
hrclrUpdateTextRow(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 320 * 9;
}
}
void hrclrUpdateDblTextRow(UInt8 *, UInt8 *, UInt8 *);
void hrclrUpdateDblText(void)
{
Int16 vert;
UInt8 *_pointer = vidImage;
dirtyVideo = false;
for (vert = 0; vert < 192; vert += 8)
{
hrclrUpdateDblTextRow(&AuxMemory[ScanlineOffsetTable[vert] + 16384], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert + 1)]);
hrclrUpdateDblTextRow(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer + 4, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 320 * 9;
}
}
void hrclrUpdateLoresRow(UInt8 *, UInt8 *, UInt8 *);
void hrclrUpdateLoresMixed(void)
{
Int16 vert;
UInt8 *_pointer = vidImage;
dirtyVideo = false;
for (vert = 0; vert < 160; vert += 8)
{
hrclrUpdateLoresRow(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 320 * 9;
}
while (vert < 192)
{
hrclrUpdateTextRow(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 320 * 9;
vert += 8;
}
}
void hrclrUpdateLores(void)
{
Int16 vert;
UInt8 *_pointer = vidImage;
dirtyVideo = false;
for (vert = 0; vert < 192; vert += 8)
{
hrclrUpdateLoresRow(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 320 * 9;
}
}
void hrclrUpdateHiresScanline(UInt8 *, UInt8 *, UInt8 *);
void hrclrUpdateHiresDblScanline(UInt8 *, UInt8 *, UInt8 *);
void hrclrUpdateHiresMixed(void)
{
Int16 vert, textpage;
UInt8 *_pointer = vidImage;
dirtyVideo = false;
for (vert = 0; vert < 160; vert++)
{
if ((vert & 7) == 0)
{
hrclrUpdateHiresDblScanline(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 640;
}
else
{
hrclrUpdateHiresScanline(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 320;
}
}
textpage = SS_ISSET(vidIOU, SS_PAGE2) ? 0x0800 : 0x0400;
while (vert < 192)
{
hrclrUpdateTextRow(&AppleMemory[ScanlineOffsetTable[vert] + textpage], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 320 * 9;
vert += 8;
}
}
void hrclrUpdateHires(void)
{
Int16 vert;
UInt8 *_pointer = vidImage;
dirtyVideo = false;
for (vert = 0; vert < 192; vert++)
{
if ((vert & 7) == 0)
{
hrclrUpdateHiresDblScanline(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 640;
}
else
{
hrclrUpdateHiresScanline(&AppleMemory[ScanlineOffsetTable[vert] + vidPageOffset], _pointer, &vidScreenCache[VID_CACHE_OFFSET(vert)]);
_pointer += 320;
}
}
}