aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/Patches/EmPatchModule.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SrcShared/Patches/EmPatchModule.cpp')
-rw-r--r--SrcShared/Patches/EmPatchModule.cpp318
1 files changed, 318 insertions, 0 deletions
diff --git a/SrcShared/Patches/EmPatchModule.cpp b/SrcShared/Patches/EmPatchModule.cpp
new file mode 100644
index 0000000..a4ad8a4
--- /dev/null
+++ b/SrcShared/Patches/EmPatchModule.cpp
@@ -0,0 +1,318 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1998-2001 Palm, Inc. or its subsidiaries.
+ Copyright (c) 2001 PocketPyro, Inc.
+ 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 "EmPatchModule.h"
+
+#include "EmPatchModuleMap.h"
+#include "EmStructs.h"
+#include "EmPalmFunction.h" // SysTrapIndex, IsLibraryTrap
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModule::EmPatchModule
+ *
+ * DESCRIPTION: Base EmPatchModule constructor
+ *
+ * PARAMETERS: mapIP Interface to the EmPatchModule map this module will be added to.
+ * nameCSP Unique name given to this EmPatchModule.
+ * loadTables boolean should ProtoPatchTables be loaded immediately?
+ * protoTable1P Optional Protopatch table 1 - AddProtoPatchTable can be used subsequently
+ * protoTable2P Optional Protopatch table 2 - AddProtoPatchTable can be used subsequently
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+EmPatchModule::EmPatchModule(const char *nameCSP, ProtoPatchTableEntry *protoTable1P, ProtoPatchTableEntry *protoTable2P)
+{
+ fContainerIP = NULL;
+
+ fProtoTableCount = 0;
+ fLoadedTableCount = 0;
+
+ memset(fProtoTables, 0, kMaxProtoTables * sizeof(ProtoPatchTableEntry *));
+
+ fName = nameCSP;
+
+ if (protoTable1P != NULL)
+ fProtoTables[fProtoTableCount++] = protoTable1P;
+
+ if (protoTable2P != NULL)
+ fProtoTables[fProtoTableCount++] = protoTable2P;
+}
+
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModule::PrvLoadProtoPatchTable
+ *
+ * DESCRIPTION: Loads the given ProtoPatch Table
+ *
+ * PARAMETERS: tableNbr - index of the internally referenced ProtoPatch tables to load
+ *
+ * RETURNED: nothing
+ *
+ ***********************************************************************/
+
+void EmPatchModule::PrvLoadProtoPatchTable (uint16 tableNbr)
+{
+ // Create a fast dispatch table for the managed module. A "fast
+ // dispatch table" is a table with a headpatch and tailpatch entry
+ // for each possible function in the module. If the function is
+ // not head or tailpatched, the corresponding entry is NULL. When
+ // a patch function is needed, the trap dispatch number is used as
+ // an index into the table in order to get the right patch function.
+ //
+ // For simplicity, "fast patch tables" are created from "proto patch
+ // tables". A proto patch table is a compact table containing the
+ // information needed to create a fast patch table. Each entry in
+ // the proto patch table is a trap-number/headpatch/tailpatch tupple.
+ // Each tuple is examined in turn. If there is a head or tail patch
+ // function for the indicated module function, that patch function
+ // is entered in the fast dispatch table, using the trap number as
+ // the index.
+
+ ProtoPatchTableEntry *protoPatchTable = fProtoTables[tableNbr];
+
+ for (long ii = 0; protoPatchTable[ii].fTrapWord; ++ii)
+ {
+ // If there is a headpatch function...
+
+ if (protoPatchTable[ii].fHeadpatch)
+ {
+ // Get the trap number.
+
+ uint16 index = ::SysTrapIndex (protoPatchTable[ii].fTrapWord);
+
+ // If the trap number is 0xA800-based, make it zero based.
+
+ if (::IsLibraryTrap (index))
+ index -= SysTrapIndex (sysLibTrapBase);
+
+ // Resize the fast patch table, if necessary.
+
+ if (index >= fHeadpatches.size ())
+ {
+ fHeadpatches.resize (index + 1);
+ }
+
+ // Add the headpatch function.
+
+ fHeadpatches[index] = protoPatchTable[ii].fHeadpatch;
+ }
+
+ // If there is a tailpatch function...
+
+ if (protoPatchTable[ii].fTailpatch)
+ {
+ // Get the trap number.
+
+ uint16 index = SysTrapIndex (protoPatchTable[ii].fTrapWord);
+
+ // If the trap number is 0xA800-based, make it zero based.
+
+ if (IsLibraryTrap (index))
+ index -= SysTrapIndex (sysLibTrapBase);
+
+ // Resize the fast patch table, if necessary.
+
+ if (index >= fTailpatches.size ())
+ {
+ fTailpatches.resize (index + 1);
+ }
+
+ // Add the tailpatch function.
+
+ fTailpatches[index] = protoPatchTable[ii].fTailpatch;
+ }
+ }
+}
+
+// ==============================================================================
+// * interface implementations
+// ==============================================================================
+// ==============================================================================
+// * IEmPatchModule
+//
+// * Interface exposed by all PatchModules
+// ==============================================================================
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModule::Initialize
+ *
+ * DESCRIPTION: Initializes the EmPatchModule component
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: patchErrNone
+ *
+ ***********************************************************************/
+
+Err EmPatchModule::Initialize(IEmPatchContainer &containerI)
+{
+ fContainerIP = &containerI;
+
+ Clear();
+ Load();
+
+ return kPatchErrNone;
+}
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModule::Reset
+ *
+ * DESCRIPTION: Resets the EmPatchModule component
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: patchErrNone
+ *
+ ***********************************************************************/
+
+Err EmPatchModule::Reset()
+{
+ return kPatchErrNone;
+}
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModule::Dispose
+ *
+ * DESCRIPTION: Disposes the EmPatchModule component
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: patchErrNone
+ *
+ ***********************************************************************/
+
+Err EmPatchModule::Dispose()
+{
+ Clear();
+ return kPatchErrNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModule::Clear
+ *
+ * DESCRIPTION: Clears the EmPatchModule component
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: patchErrNone
+ *
+ ***********************************************************************/
+
+Err EmPatchModule::Clear()
+{
+ fHeadpatches.clear ();
+ fTailpatches.clear ();
+
+ fLoadedTableCount = 0;
+
+ return kPatchErrNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModule::Load
+ *
+ * DESCRIPTION: Loads the EmPatchModule component
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: patchErrNone
+ *
+ ***********************************************************************/
+
+Err EmPatchModule::Load()
+{
+ while (fLoadedTableCount < fProtoTableCount)
+ {
+ PrvLoadProtoPatchTable(fLoadedTableCount++);
+ }
+
+ return kPatchErrNone;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmPatchModule::GetName
+ *
+ * DESCRIPTION: Gets a reference to the unique string name of the EmPatchModule component
+ *
+ * PARAMETERS: none
+ *
+ * RETURNED: reference to the unique string name
+ *
+ ***********************************************************************/
+
+const string &EmPatchModule::GetName()
+{
+ return fName;
+}
+
+
+// Return the patch function for the given module function The given
+// module function *must* be given as a zero-based index. If there is
+// no patch function for the modeule function, procP == NULL.
+//
+Err EmPatchModule::GetHeadpatch (uint16 index, HeadpatchProc& procP)
+{
+ Err err = kPatchErrInvalidIndex;
+ procP = NULL;
+
+ if (index < fHeadpatches.size ())
+ {
+ procP = fHeadpatches[index];
+ err = kPatchErrNone;
+ }
+
+ return err;
+}
+
+
+// Return the patch function for the given module function The given
+// module function *must* be given as a zero-based index. If there is
+// no patch function for the modeule function, procP == NULL.
+//
+Err EmPatchModule::GetTailpatch (uint16 index, TailpatchProc& procP)
+{
+ Err err = kPatchErrInvalidIndex;
+ procP = NULL;
+
+ if (index < fTailpatches.size ())
+ {
+ procP = fTailpatches[index];
+ err = kPatchErrNone;
+ }
+
+ return err;
+}
+
+
+// ==============================================================================
+// * END IEmPatchModule
+// ==============================================================================