aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/EmScreen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SrcShared/EmScreen.cpp')
-rw-r--r--SrcShared/EmScreen.cpp281
1 files changed, 281 insertions, 0 deletions
diff --git a/SrcShared/EmScreen.cpp b/SrcShared/EmScreen.cpp
new file mode 100644
index 0000000..1808f3b
--- /dev/null
+++ b/SrcShared/EmScreen.cpp
@@ -0,0 +1,281 @@
+/* -*- 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 "EmScreen.h"
+
+#include "EmHAL.h" // EmHAL:: GetLCDBeginEnd
+#include "EmMemory.h" // CEnableFullAccess
+#include "MetaMemory.h" // MetaMemory::MarkScreen
+
+
+static emuptr gScreenDirtyLow;
+static emuptr gScreenDirtyHigh;
+
+static emuptr gScreenBegin;
+static emuptr gScreenEnd;
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Initialize
+ *
+ * DESCRIPTION: Standard initialization function. Responsible for
+ * initializing this sub-system when a new session is
+ * created. Will be followed by at least one call to
+ * Reset or Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Initialize (void)
+{
+ gScreenDirtyLow = EmMemEOM;
+ gScreenDirtyHigh = EmMemNULL;
+
+ gScreenBegin = EmMemNULL;
+ gScreenEnd = EmMemNULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Reset
+ *
+ * DESCRIPTION: Standard reset function. Sets the sub-system to a
+ * default state. This occurs not only on a Reset (as
+ * from the menu item), but also when the sub-system
+ * is first initialized (Reset is called after Initialize)
+ * as well as when the system is re-loaded from an
+ * insufficient session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Reset (void)
+{
+ gScreenDirtyLow = EmMemNULL;
+ gScreenDirtyHigh = EmMemEOM;
+
+ gScreenBegin = EmMemNULL;
+ gScreenEnd = EmMemNULL;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Save
+ *
+ * DESCRIPTION: Standard save function. Saves any sub-system state to
+ * the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Save (SessionFile&)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Load
+ *
+ * DESCRIPTION: Standard load function. Loads any sub-system state
+ * from the given session file.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Load (SessionFile&)
+{
+ gScreenDirtyLow = EmMemNULL;
+ gScreenDirtyHigh = EmMemEOM;
+
+ EmHAL::GetLCDBeginEnd (gScreenBegin, gScreenEnd);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::Dispose
+ *
+ * DESCRIPTION: Standard dispose function. Completely release any
+ * resources acquired or allocated in Initialize and/or
+ * Load.
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::Dispose (void)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::MarkDirty
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::MarkDirty (emuptr address, uint32 size)
+{
+ /*
+ SUBTLE BUG NOTE: Both of these tests need to be performed.
+ Originally, I had this as an if (...) ... else if (...) ... After
+ all, how could a given address be above the high- water mark if it
+ was below the low-water mark? "Obviously", it couldn't, so I didn't
+ see the need to test against the high-water mark if we were below
+ the low-water mark.
+
+ Well, duh, that assumption was false. After the LCD buffer is
+ copied to the screen, we set the low-water mark to the end of the
+ buffer and the high-water mark to the beginning of the buffer. If
+ the screen is modified in such a way that each pixel affected
+ appears lower in memory than any previous pixel (as happens when we
+ scroll a document down), then we always entered the low-water mark
+ of the code below; we never entered the high-water mark of the code.
+ Thus, the high-water mark stayed set to the beginning of the
+ buffer, giving us a NULL update range.
+ */
+
+ if (address < gScreenDirtyLow)
+ {
+ gScreenDirtyLow = address;
+ }
+
+ if (address + size > gScreenDirtyHigh)
+ {
+ gScreenDirtyHigh = address + size;
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::InvalidateAll
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+void EmScreen::InvalidateAll (void)
+{
+ gScreenDirtyLow = EmMemNULL;
+ gScreenDirtyHigh = EmMemEOM;
+
+ emuptr newScreenBegin;
+ emuptr newScreenEnd;
+ EmHAL::GetLCDBeginEnd (newScreenBegin, newScreenEnd);
+
+ if (newScreenBegin != gScreenBegin || newScreenEnd != gScreenEnd)
+ {
+ MetaMemory::UnmarkScreen (gScreenBegin, gScreenEnd);
+
+ gScreenBegin = newScreenBegin;
+ gScreenEnd = newScreenEnd;
+
+ MetaMemory::MarkScreen (gScreenBegin, gScreenEnd);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmScreen::GetBits
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+Bool EmScreen::GetBits (EmScreenUpdateInfo& info)
+{
+ // Always return whether or not the LCD is on.
+
+ info.fLCDOn = EmHAL::GetLCDScreenOn ();
+
+ // Get the first and last scanlines to update. This is a *big* win
+ // when running Gremlins. Without this check, a typical test ran
+ // 240 seconds. With the check, the test ran 170 seconds.
+
+ // Get the screen begin and end. We'll be clipping against this
+ // range (just in case screenLow and/or screenHigh got out of whack,
+ // which might happen in a multi-threaded system and we aren't using
+ // synchronization objects).
+
+ emuptr screenBegin;
+ emuptr screenEnd;
+ EmHAL::GetLCDBeginEnd (screenBegin, screenEnd);
+
+ // Get the range of bytes affected, clipping to the range of the
+ // screen. From this information, we can determine the first and
+ // last affected scanlines.
+
+ info.fScreenLow = max (gScreenDirtyLow, screenBegin);
+ info.fScreenHigh = min (gScreenDirtyHigh, screenEnd);
+
+ // Reset gScreenDirtyLow/High with sentinel values so that they can
+ // be munged again by EmScreen::MarkDirty.
+
+ gScreenDirtyLow = EmMemEOM;
+ gScreenDirtyHigh = EmMemNULL;
+
+ // If no lines need to be updated, we can return now.
+
+ if (info.fScreenLow >= info.fScreenHigh)
+ {
+ return false;
+ }
+
+ // Get the current state of things. Do this only if the LCD is on.
+ // If the LCD is off, we may not be able to get the contents of its
+ // frame buffer (the bus to the buffer may be disabled).
+
+ if (info.fLCDOn)
+ {
+ CEnableFullAccess munge; // Remove blocks on memory access.
+
+ EmHAL::GetLCDScanlines (info);
+ }
+
+ return true;
+}