diff options
Diffstat (limited to 'SrcShared/Hardware/EmRegsSED1376.cpp')
-rw-r--r-- | SrcShared/Hardware/EmRegsSED1376.cpp | 860 |
1 files changed, 860 insertions, 0 deletions
diff --git a/SrcShared/Hardware/EmRegsSED1376.cpp b/SrcShared/Hardware/EmRegsSED1376.cpp new file mode 100644 index 0000000..223c24a --- /dev/null +++ b/SrcShared/Hardware/EmRegsSED1376.cpp @@ -0,0 +1,860 @@ +/* -*- mode: C++; tab-width: 4 -*- */ +/* ===================================================================== *\ + Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries. + All rights reserved. + + This file is part of the Palm OS Emulator. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +\* ===================================================================== */ + +#include "EmCommon.h" +#include "EmRegsSED1376.h" + +#include "EmMemory.h" // EmMem_memcpy +#include "EmScreen.h" // EmScreen::InvalidateAll +#include "EmPixMap.h" // EmPixMap::GetLCDScanlines +#include "SessionFile.h" // WriteSED1376RegsType + + +// Given a register (specified by its field name), return its address +// in emulated space. + +#define addressof(reg) \ + (this->GetAddressStart () + fRegs.offsetof_##reg ()) + + +// Macro to help the installation of handlers for a register. + +#define INSTALL_HANDLER(read, write, reg) \ + this->SetHandler ( (ReadFunction) &EmRegsSED1376::read, \ + (WriteFunction) &EmRegsSED1376::write, \ + addressof (reg), \ + fRegs.reg.GetSize ()) + +// Panel type register [10h] +#define sed1376MonoMask 0x40 + +// Display mode register [70h] +#define sed1376DisplayBlankMask 0x80 +#define sed1376BPPMask 0x07 +#define sed1376BPPShift 0x00 + +// REG[0x70] displayMode register +// (Same as previous set, but with Handspring names for their contributed code) +#define sed1376DisplayModeBlank 0x80 +#define sed1376DisplayModeDitherOff 0x40 +#define sed1376DisplayModeHwInvert 0x20 +#define sed1376DisplayModeSwInvert 0x10 +#define sed1376DisplayModeDepthMask 0x07 +#define sed1376DisplayModeDepth16 0x04 +#define sed1376DisplayModeDepth8 0x03 +#define sed1376DisplayModeDepth4 0x02 +#define sed1376DisplayModeDepth2 0x01 +#define sed1376DisplayModeDepth1 0x00 + +// Special effects register [71h] +#define sed1376WordSwapMask 0x80 +#define sed1376ByteSwapMask 0x40 +#define sed1376SubWindowEnableMask 0x10 + +#define hwrDisplayGPIOPCI 0x08 // in GPIOStatusControl0 +#define hwrDisplayGPIOEL_ON 0x10 // in GPIOStatusControl0 +#define hwrDisplayGPIOLCD_ON 0x20 // in GPIOStatusControl0 +#define hwrDisplayGPIOMOD 0x40 // in GPIOStatusControl0 + +// The current SED1376 driver code is completely whacked. It's initialized to use +// the main display for drawing (see HwrDisplayInit in HwrDisplayBootSED1376.c), but +// if you change the base address, it (a) always returns the base of the embedded +// SRAM buffer as the old base address, and (b) stores the new base address in +// ovlyStartAddress (see PrvDisplayBaseAddr in HwrDisplaySED1376.c). Also, the +// splash screen appears to be drawn relative to ovlyStartAddress. Finally, +// there appears to be code to draw a border in the main screen around the +// overlay screen (see PrvDisplayBorder in HwrDisplayBootSED1376.c), however, +// the mainStartAddress registers are never changed to point to this border. +// On top of that, the border is only programmed on the left and right of the +// of the overlay screen, not on the top and bottom. + +#define OVERLAY_IS_MAIN 1 + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::EmRegsSED1376 +// --------------------------------------------------------------------------- + +EmRegsSED1376::EmRegsSED1376 (emuptr baseRegsAddr, emuptr baseVideoAddr) : + fBaseRegsAddr (baseRegsAddr), + fBaseVideoAddr (baseVideoAddr), + fRegs () +{ +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::~EmRegsSED1376 +// --------------------------------------------------------------------------- + +EmRegsSED1376::~EmRegsSED1376 (void) +{ +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::Initialize +// --------------------------------------------------------------------------- + +void EmRegsSED1376::Initialize (void) +{ + EmRegs::Initialize (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::Reset +// --------------------------------------------------------------------------- + +void EmRegsSED1376::Reset (Bool hardwareReset) +{ + EmRegs::Reset (hardwareReset); + + if (hardwareReset) + { + memset (fRegs.GetPtr (), 0, fRegs.GetSize ()); + +// EmAssert ((sed1376ProductCodeExpected | sed1376RevisionCodeExpected) == 0x28); + fRegs.productRevisionCode = 0x28; + fRegs.displayBufferSize = 20; // 80K / 4K + fRegs.configurationReadback = 0; + } +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::Save +// --------------------------------------------------------------------------- + +void EmRegsSED1376::Save (SessionFile& f) +{ + EmRegs::Save (f); + + f.WriteSED1376RegsType (*(SED1376RegsType*) fRegs.GetPtr ()); + f.WriteSED1376Palette (fClutData); +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::Load +// --------------------------------------------------------------------------- + +void EmRegsSED1376::Load (SessionFile& f) +{ + EmRegs::Load (f); + + // Read in the SED registers. + + if (!f.ReadSED1376RegsType (*(SED1376RegsType*) fRegs.GetPtr ())) + { + f.SetCanReload (false); + } + + // Read in the LCD palette. + + if (!f.ReadSED1376Palette (fClutData)) + { + f.SetCanReload (false); + } +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::Dispose +// --------------------------------------------------------------------------- + +void EmRegsSED1376::Dispose (void) +{ + EmRegs::Dispose (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::SetSubBankHandlers +// --------------------------------------------------------------------------- + +void EmRegsSED1376::SetSubBankHandlers (void) +{ + // Install base handlers. + + EmRegs::SetSubBankHandlers (); + + // Now add standard/specialized handers for the defined registers. + + INSTALL_HANDLER (StdReadBE, NullWrite, productRevisionCode); + INSTALL_HANDLER (StdReadBE, NullWrite, displayBufferSize); + INSTALL_HANDLER (StdReadBE, NullWrite, configurationReadback); + INSTALL_HANDLER (StdReadBE, StdWriteBE, memoryClockConfiguration); + INSTALL_HANDLER (StdReadBE, StdWriteBE, pixelClockConfiguration); + INSTALL_HANDLER (StdReadBE, StdWriteBE, lutWriteBlue); + INSTALL_HANDLER (StdReadBE, StdWriteBE, lutWriteGreen); + INSTALL_HANDLER (StdReadBE, StdWriteBE, lutWriteRed); + INSTALL_HANDLER (ZeroRead, lutWriteAddressWrite, lutWriteAddress); + INSTALL_HANDLER (StdReadBE, NullWrite, lutReadBlue); + INSTALL_HANDLER (StdReadBE, NullWrite, lutReadGreen); + INSTALL_HANDLER (StdReadBE, NullWrite, lutReadRed); + INSTALL_HANDLER (ZeroRead, lutReadAddressWrite, lutReadAddress); + INSTALL_HANDLER (StdReadBE, StdWriteBE, panelType); + INSTALL_HANDLER (StdReadBE, StdWriteBE, MODRate); + INSTALL_HANDLER (StdReadBE, StdWriteBE, horizontalTotal); + INSTALL_HANDLER (StdReadBE, invalidateWrite, horizontalPeriod); + INSTALL_HANDLER (StdReadBE, StdWriteBE, horizontalPeriodStart0); + INSTALL_HANDLER (StdReadBE, StdWriteBE, horizontalPeriodStart1); + INSTALL_HANDLER (StdReadBE, StdWriteBE, verticalTotal0); + INSTALL_HANDLER (StdReadBE, StdWriteBE, verticalTotal1); + INSTALL_HANDLER (StdReadBE, invalidateWrite, verticalPeriod0); + INSTALL_HANDLER (StdReadBE, invalidateWrite, verticalPeriod1); + INSTALL_HANDLER (StdReadBE, StdWriteBE, verticalPeriodStart0); + INSTALL_HANDLER (StdReadBE, StdWriteBE, verticalPeriodStart1); + INSTALL_HANDLER (StdReadBE, StdWriteBE, FPLINEPulseWidth); + INSTALL_HANDLER (StdReadBE, StdWriteBE, FPLINEPulseStart0); + INSTALL_HANDLER (StdReadBE, StdWriteBE, FPLINEPulseStart1); + INSTALL_HANDLER (StdReadBE, StdWriteBE, FPFRAMEPulseWidth); + INSTALL_HANDLER (StdReadBE, StdWriteBE, FPFRAMEPulseStart0); + INSTALL_HANDLER (StdReadBE, StdWriteBE, FPFRAMEPulseStart1); + INSTALL_HANDLER (StdReadBE, StdWriteBE, DTFD_GCPIndex); + INSTALL_HANDLER (StdReadBE, StdWriteBE, DTFD_GCPData); + INSTALL_HANDLER (StdReadBE, invalidateWrite, displayMode); + INSTALL_HANDLER (StdReadBE, invalidateWrite, specialEffects); + INSTALL_HANDLER (StdReadBE, invalidateWrite, mainStartAddress0); + INSTALL_HANDLER (StdReadBE, invalidateWrite, mainStartAddress1); + INSTALL_HANDLER (StdReadBE, invalidateWrite, mainStartAddress2); + INSTALL_HANDLER (StdReadBE, invalidateWrite, mainLineAddressOffset0); + INSTALL_HANDLER (StdReadBE, invalidateWrite, mainLineAddressOffset1); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartAddress0); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartAddress1); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartAddress2); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyLineAddressOffset0); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyLineAddressOffset1); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartXPosition0); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartXPosition1); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartYPosition0); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyStartYPosition1); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyEndXPosition0); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyEndXPosition1); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyEndYPosition0); + INSTALL_HANDLER (StdReadBE, invalidateWrite, ovlyEndYPosition1); + INSTALL_HANDLER (powerSaveConfigurationRead, StdWriteBE, powerSaveConfiguration); + INSTALL_HANDLER (StdReadBE, StdWriteBE, SoftwareReset); + INSTALL_HANDLER (StdReadBE, StdWriteBE, scratchPad0); + INSTALL_HANDLER (StdReadBE, StdWriteBE, scratchPad1); + INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOConfiguration0); + INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOConfiguration1); + INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOStatusControl0); + INSTALL_HANDLER (StdReadBE, StdWriteBE, GPIOStatusControl1); + INSTALL_HANDLER (StdReadBE, StdWriteBE, PWMClockCVPulseControl); + INSTALL_HANDLER (StdReadBE, StdWriteBE, PWMClockCVPulseConfig); + INSTALL_HANDLER (StdReadBE, StdWriteBE, CVPulseBurstLength); + INSTALL_HANDLER (StdReadBE, StdWriteBE, PWMOutDutyCycle); +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::GetRealAddress +// --------------------------------------------------------------------------- + +uint8* EmRegsSED1376::GetRealAddress (emuptr address) +{ + return (uint8*) fRegs.GetPtr () + address - this->GetAddressStart (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::GetAddressStart +// --------------------------------------------------------------------------- + +emuptr EmRegsSED1376::GetAddressStart (void) +{ + return fBaseRegsAddr; +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::GetAddressRange +// --------------------------------------------------------------------------- + +uint32 EmRegsSED1376::GetAddressRange (void) +{ + return fRegs.GetSize (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::GetLCDScreenOn +// --------------------------------------------------------------------------- + +Bool EmRegsSED1376::GetLCDScreenOn (void) +{ +// return ((fRegs.displayMode) & sed1376DisplayBlankMask) == 0; + return ((fRegs.GPIOStatusControl0) & hwrDisplayGPIOLCD_ON) != 0; +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::GetLCDBacklightOn +// --------------------------------------------------------------------------- + +Bool EmRegsSED1376::GetLCDBacklightOn (void) +{ + return ((fRegs.GPIOStatusControl0) & hwrDisplayGPIOEL_ON) != 0; +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::GetLCDHasFrame +// --------------------------------------------------------------------------- + +Bool EmRegsSED1376::GetLCDHasFrame (void) +{ + return true; +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::invalidateWrite +// --------------------------------------------------------------------------- + +void EmRegsSED1376::invalidateWrite (emuptr address, int size, uint32 value) +{ + this->StdWriteBE (address, size, value); + EmScreen::InvalidateAll (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::powerSaveConfigurationRead +// --------------------------------------------------------------------------- + +uint32 EmRegsSED1376::powerSaveConfigurationRead (emuptr address, int size) +{ + UNUSED_PARAM(address) + UNUSED_PARAM(size) + + // Always set the vertical non-display status high since in the real + // hardware, the ROM will check this flag in order to write the CLUT + // registers. + + return (fRegs.powerSaveConfiguration) | 0x80; +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::lutWriteAddressWrite +// --------------------------------------------------------------------------- + +void EmRegsSED1376::lutWriteAddressWrite (emuptr address, int size, uint32 value) +{ + UNUSED_PARAM(address) + UNUSED_PARAM(size) + + value &= 0x0FF; + + uint8 red = fRegs.lutWriteRed; + uint8 green = fRegs.lutWriteGreen; + uint8 blue = fRegs.lutWriteBlue; + + fClutData[value] = RGBType ((red & 0xFC) | (red >> 6), + (green & 0xFC) | (green >> 6), + (blue & 0xFC) | (blue >> 6)); + + EmScreen::InvalidateAll (); +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::lutReadAddressWrite +// --------------------------------------------------------------------------- + +void EmRegsSED1376::lutReadAddressWrite (emuptr address, int size, uint32 value) +{ + UNUSED_PARAM(address) + UNUSED_PARAM(size) + + value &= 0x0FF; + + RGBType rgb = fClutData[value]; + + fRegs.lutReadRed = rgb.fRed & 0xFC; + fRegs.lutReadGreen = rgb.fGreen & 0xFC; + fRegs.lutReadBlue = rgb.fBlue & 0xFC; +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376::PrvGetPalette +// --------------------------------------------------------------------------- + +void EmRegsSED1376::PrvGetPalette (RGBList& thePalette) +{ + Bool mono = (fRegs.displayMode & sed1376MonoMask) != 0; + int32 bpp = 1 << ((fRegs.displayMode & sed1376BPPMask) >> sed1376BPPShift); + int32 numColors = 1 << bpp; + + thePalette.resize (numColors); + + for (int ii = 0; ii < numColors; ++ii) + { + if (mono) + { + uint8 green = fClutData[ii].fGreen; + thePalette[ii].fRed = green; + thePalette[ii].fGreen = green; + thePalette[ii].fBlue = green; + } + else + { + thePalette[ii] = fClutData[ii]; + } + } +} + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376VisorPrism::EmRegsSED1376VisorPrism +// --------------------------------------------------------------------------- + +EmRegsSED1376VisorPrism::EmRegsSED1376VisorPrism (emuptr baseRegsAddr, + emuptr baseVideoAddr) : + EmRegsSED1376 (baseRegsAddr, baseVideoAddr) +{ +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376VisorPrism::~EmRegsSED1376VisorPrism +// --------------------------------------------------------------------------- + +EmRegsSED1376VisorPrism::~EmRegsSED1376VisorPrism (void) +{ +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376VisorPrism::SetSubBankHandlers +// --------------------------------------------------------------------------- + +void EmRegsSED1376VisorPrism::SetSubBankHandlers (void) +{ + // Install base handlers. + + EmRegsSED1376::SetSubBankHandlers (); + + // Now add standard/specialized handers for the defined registers. + +#undef INSTALL_HANDLER +#define INSTALL_HANDLER(read, write, reg) \ + this->SetHandler ( (ReadFunction) &EmRegsSED1376VisorPrism::read, \ + (WriteFunction) &EmRegsSED1376VisorPrism::write, \ + addressof (reg), \ + fRegs.reg.GetSize ()) + + INSTALL_HANDLER (StdReadBE, reservedWrite, reserved); +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376VisorPrism::GetLCDBeginEnd +// --------------------------------------------------------------------------- + +void EmRegsSED1376VisorPrism::GetLCDBeginEnd (emuptr& begin, emuptr& end) +{ + // Get the screen metrics. + + // The hardware is written to in reverse, so the mainStartOffsetX registers + // report the END of the frame buffer, not the beginning. + emuptr baseAddr = fBaseVideoAddr; + + int32 width = ((fRegs.horizontalPeriod + 1) * 8); + int32 height = ((fRegs.verticalPeriod1 << 8) | fRegs.verticalPeriod0) + 1; + int32 rowBytes = ((width * this->PrvGetLCDDepth ()) / 8); + + begin = baseAddr; + end = baseAddr + rowBytes * height; +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376VisorPrism::GetLCDScanlines +// --------------------------------------------------------------------------- + +void EmRegsSED1376VisorPrism::GetLCDScanlines (EmScreenUpdateInfo& info) +{ + // Get the screen metrics. + + Bool byteSwapped = (fRegs.specialEffects & sed1376ByteSwapMask) != 0; + Bool mono = (fRegs.displayMode & sed1376MonoMask) != 0; + int32 bpp = 1 << ((fRegs.displayMode & sed1376BPPMask) >> sed1376BPPShift); + + // The hardware is written to in reverse, so the mainStartOffsetX registers + // report the END of the frame buffer, not the beginning. + emuptr baseAddr = fBaseVideoAddr; + + int32 width = ((fRegs.horizontalPeriod + 1) * 8); + int32 height = ((fRegs.verticalPeriod1 << 8) | fRegs.verticalPeriod0) + 1; + int32 rowBytes = ((width * this->PrvGetLCDDepth ()) / 8); + + info.fLeftMargin = 0; + + if (bpp <= 8) + { + EmPixMapFormat format = bpp == 1 ? kPixMapFormat1 : + bpp == 2 ? kPixMapFormat2 : + bpp == 4 ? kPixMapFormat4 : + kPixMapFormat8; + + RGBList colorTable; + this->PrvGetPalette (colorTable); + + // Set format, size, and color table of EmPixMap. + + info.fImage.SetSize (EmPoint (width, height)); + info.fImage.SetFormat (format); + info.fImage.SetRowBytes (rowBytes); + info.fImage.SetColorTable (colorTable); + + // Determine first and last scanlines to fetch, and fetch them. + + info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes; + info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1; + + long firstLineOffset = info.fFirstLine * rowBytes; + long lastLineOffset = info.fLastLine * rowBytes; + + EmMem_memcpy ( + (void*) ((uint8*) info.fImage.GetBits () + firstLineOffset), + baseAddr + firstLineOffset, + lastLineOffset - firstLineOffset); + } + else + { + // Set depth, size, and color table of EmPixMap. + + info.fImage.SetSize (EmPoint (width, height)); + info.fImage.SetFormat (kPixMapFormat24RGB); + + // Determine first and last scanlines to fetch. + + info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes; + info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1; + + // Get location and rowBytes of source bytes. + + uint8* srcStart = EmMemGetRealAddress (baseAddr); + int32 srcRowBytes = rowBytes; + uint8* srcPtr = srcStart + srcRowBytes * info.fFirstLine; + uint8* srcPtr0 = srcPtr; + + // Get location and rowBytes of destination bytes. + + uint8* destStart = (uint8*) info.fImage.GetBits (); + int32 destRowBytes = info.fImage.GetRowBytes (); + uint8* destPtr = destStart + destRowBytes * info.fFirstLine; + uint8* destPtr0 = destPtr; + + // Get height of range to copy. + + int32 height = info.fLastLine - info.fFirstLine; + + // Copy the pixels from source to dest. + + for (int yy = 0; yy < height; ++yy) + { + for (int xx = 0; xx < width; ++xx) + { + uint8 p1 = EmMemDoGet8 (srcPtr++); // GGGBBBBB + uint8 p2 = EmMemDoGet8 (srcPtr++); // RRRRRGGG + + // Merge the two together so that we get RRRRRGGG GGGBBBBB + + uint16 p; + + if (!byteSwapped) + p = (p2 << 8) | p1; + else + p = (p1 << 8) | p2; + + // Shift the bits around, forming RRRRRrrr, GGGGGGgg, and + // BBBBBbbb values, where the lower-case bits are copies of + // the least significant bits in the upper-case bits. + // + // Note that all of this could also be done with three 64K + // lookup tables. If speed is an issue, we might want to + // investigate that. + + if (mono) + { + uint8 green = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03); + *destPtr++ = green; + *destPtr++ = green; + *destPtr++ = green; + } + else + { + *destPtr++ = ((p >> 8) & 0xF8) | ((p >> 11) & 0x07); + *destPtr++ = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03); + *destPtr++ = ((p << 3) & 0xF8) | ((p >> 0) & 0x07); + } + } + + srcPtr = srcPtr0 += srcRowBytes; + destPtr = destPtr0 += destRowBytes; + } + } +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376VisorPrism::PrvGetLCDDepth +// --------------------------------------------------------------------------- + +int32 EmRegsSED1376VisorPrism::PrvGetLCDDepth (void) +{ + UInt8 depth = fRegs.displayMode; + + depth &= sed1376DisplayModeDepthMask; + + switch (depth) + { + case sed1376DisplayModeDepth16: return 16; + case sed1376DisplayModeDepth8: return 8; + case sed1376DisplayModeDepth4: return 4; + case sed1376DisplayModeDepth2: return 2; + case sed1376DisplayModeDepth1: return 1; + default: EmAssert (false); + } + + return 8; +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376VisorPrism::reservedWrite +// --------------------------------------------------------------------------- + +void EmRegsSED1376VisorPrism::reservedWrite (emuptr address, int size, uint32 value) +{ + UNUSED_PARAM (address); + UNUSED_PARAM (size); + UNUSED_PARAM (value); +} + + +#pragma mark - + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376PalmGeneric::EmRegsSED1376PalmGeneric +// --------------------------------------------------------------------------- + +EmRegsSED1376PalmGeneric::EmRegsSED1376PalmGeneric (emuptr baseRegsAddr, + emuptr baseVideoAddr) : + EmRegsSED1376 (baseRegsAddr, baseVideoAddr) +{ +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376PalmGeneric::~EmRegsSED1376PalmGeneric +// --------------------------------------------------------------------------- + +EmRegsSED1376PalmGeneric::~EmRegsSED1376PalmGeneric (void) +{ +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376PalmGeneric::GetLCDBeginEnd +// --------------------------------------------------------------------------- + +void EmRegsSED1376PalmGeneric::GetLCDBeginEnd (emuptr& begin, emuptr& end) +{ + // Get the screen metrics. + +// Bool wordSwapped = (fRegs.specialEffects & sed1376WordSwapMask) != 0; +// Bool byteSwapped = (fRegs.specialEffects & sed1376ByteSwapMask) != 0; +// int32 bpp = 1 << ((fRegs.displayMode & sed1376BPPMask) >> sed1376BPPShift); +#if !OVERLAY_IS_MAIN +// int32 width = ((fRegs.horizontalPeriod + 1) * 8); + int32 height = ((fRegs.verticalPeriod1 << 8) | fRegs.verticalPeriod0) + 1; + int32 rowBytes = ((fRegs.mainLineAddressOffset1 << 8) | fRegs.mainLineAddressOffset0) * 4; + uint32 offset = (fRegs.mainStartAddress2 << 18) | + (fRegs.mainStartAddress1 << 10) | + (fRegs.mainStartAddress0 << 2); +#else +// int32 left = ((fRegs.ovlyStartXPosition1 << 8) | fRegs.ovlyStartXPosition0) * 32 / bpp; +// int32 right = ((fRegs.ovlyEndXPosition1 << 8) | fRegs.ovlyEndXPosition0) * 32 / bpp; + int32 top = ((fRegs.ovlyStartYPosition1 << 8) | fRegs.ovlyStartYPosition0); + int32 bottom = ((fRegs.ovlyEndYPosition1 << 8) | fRegs.ovlyEndYPosition0); + +// int32 width = right - left + (32 / bpp); + int32 height = bottom - top + 1; + int32 rowBytes = ((fRegs.ovlyLineAddressOffset1 << 8) | fRegs.ovlyLineAddressOffset0) * 4; + uint32 offset = (fRegs.ovlyStartAddress2 << 18) | + (fRegs.ovlyStartAddress1 << 10) | + (fRegs.ovlyStartAddress0 << 2); +#endif + emuptr baseAddr = fBaseVideoAddr + offset; + + begin = baseAddr; + end = baseAddr + rowBytes * height; +} + + +// --------------------------------------------------------------------------- +// ¥ EmRegsSED1376PalmGeneric::GetLCDScanlines +// --------------------------------------------------------------------------- + +void EmRegsSED1376PalmGeneric::GetLCDScanlines (EmScreenUpdateInfo& info) +{ + // Get the screen metrics. + +// Bool wordSwapped = (fRegs.specialEffects & sed1376WordSwapMask) != 0; + Bool byteSwapped = (fRegs.specialEffects & sed1376ByteSwapMask) != 0; + Bool mono = (fRegs.displayMode & sed1376MonoMask) != 0; + int32 bpp = 1 << ((fRegs.displayMode & sed1376BPPMask) >> sed1376BPPShift); +#if !OVERLAY_IS_MAIN + int32 width = ((fRegs.horizontalPeriod + 1) * 8); + int32 height = ((fRegs.verticalPeriod1 << 8) | fRegs.verticalPeriod0) + 1; + int32 rowBytes = ((fRegs.mainLineAddressOffset1 << 8) | fRegs.mainLineAddressOffset0) * 4; + uint32 offset = (fRegs.mainStartAddress2 << 18) | + (fRegs.mainStartAddress1 << 10) | + (fRegs.mainStartAddress0 << 2); +#else + int32 left = ((fRegs.ovlyStartXPosition1 << 8) | fRegs.ovlyStartXPosition0) * 32 / bpp; + int32 right = ((fRegs.ovlyEndXPosition1 << 8) | fRegs.ovlyEndXPosition0) * 32 / bpp; + int32 top = ((fRegs.ovlyStartYPosition1 << 8) | fRegs.ovlyStartYPosition0); + int32 bottom = ((fRegs.ovlyEndYPosition1 << 8) | fRegs.ovlyEndYPosition0); + + int32 width = right - left + (32 / bpp); + int32 height = bottom - top + 1; + int32 rowBytes = ((fRegs.ovlyLineAddressOffset1 << 8) | fRegs.ovlyLineAddressOffset0) * 4; + uint32 offset = (fRegs.ovlyStartAddress2 << 18) | + (fRegs.ovlyStartAddress1 << 10) | + (fRegs.ovlyStartAddress0 << 2); +#endif + emuptr baseAddr = fBaseVideoAddr + offset; + + info.fLeftMargin = 0; + + if (bpp <= 8) + { + EmPixMapFormat format = bpp == 1 ? kPixMapFormat1 : + bpp == 2 ? kPixMapFormat2 : + bpp == 4 ? kPixMapFormat4 : + kPixMapFormat8; + + RGBList colorTable; + this->PrvGetPalette (colorTable); + + // Set format, size, and color table of EmPixMap. + + info.fImage.SetSize (EmPoint (width, height)); + info.fImage.SetFormat (format); + info.fImage.SetRowBytes (rowBytes); + info.fImage.SetColorTable (colorTable); + + // Determine first and last scanlines to fetch, and fetch them. + + info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes; + info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1; + + long firstLineOffset = info.fFirstLine * rowBytes; + long lastLineOffset = info.fLastLine * rowBytes; + + EmMem_memcpy ( + (void*) ((uint8*) info.fImage.GetBits () + firstLineOffset), + baseAddr + firstLineOffset, + lastLineOffset - firstLineOffset); + } + else + { + // Set depth, size, and color table of EmPixMap. + + info.fImage.SetSize (EmPoint (width, height)); + info.fImage.SetFormat (kPixMapFormat24RGB); + + // Determine first and last scanlines to fetch. + + info.fFirstLine = (info.fScreenLow - baseAddr) / rowBytes; + info.fLastLine = (info.fScreenHigh - baseAddr - 1) / rowBytes + 1; + + // Get location and rowBytes of source bytes. + + uint8* srcStart = EmMemGetRealAddress (baseAddr); + int32 srcRowBytes = rowBytes; + uint8* srcPtr = srcStart + srcRowBytes * info.fFirstLine; + uint8* srcPtr0 = srcPtr; + + // Get location and rowBytes of destination bytes. + + uint8* destStart = (uint8*) info.fImage.GetBits (); + int32 destRowBytes = info.fImage.GetRowBytes (); + uint8* destPtr = destStart + destRowBytes * info.fFirstLine; + uint8* destPtr0 = destPtr; + + // Get height of range to copy. + + int32 height = info.fLastLine - info.fFirstLine; + + // Copy the pixels from source to dest. + + for (int yy = 0; yy < height; ++yy) + { + for (int xx = 0; xx < width; ++xx) + { + uint8 p1 = EmMemDoGet8 (srcPtr++); // GGGBBBBB + uint8 p2 = EmMemDoGet8 (srcPtr++); // RRRRRGGG + + // Merge the two together so that we get RRRRRGGG GGGBBBBB + + uint16 p; + + if (!byteSwapped) + p = (p2 << 8) | p1; + else + p = (p1 << 8) | p2; + + // Shift the bits around, forming RRRRRrrr, GGGGGGgg, and + // BBBBBbbb values, where the lower-case bits are copies of + // the least significant bits in the upper-case bits. + // + // Note that all of this could also be done with three 64K + // lookup tables. If speed is an issue, we might want to + // investigate that. + + if (mono) + { + uint8 green = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03); + *destPtr++ = green; + *destPtr++ = green; + *destPtr++ = green; + } + else + { + *destPtr++ = ((p >> 8) & 0xF8) | ((p >> 11) & 0x07); + *destPtr++ = ((p >> 3) & 0xFC) | ((p >> 5) & 0x03); + *destPtr++ = ((p << 3) & 0xF8) | ((p >> 0) & 0x07); + } + } + + srcPtr = srcPtr0 += srcRowBytes; + destPtr = destPtr0 += destRowBytes; + } + } + + if (!this->GetLCDBacklightOn ()) + { + info.fImage.ChangeTone (-10, info.fFirstLine, info.fLastLine); + } +} |