diff options
Diffstat (limited to 'SrcShared/Patches/EmPatchModuleSys.cpp')
-rw-r--r-- | SrcShared/Patches/EmPatchModuleSys.cpp | 3217 |
1 files changed, 3217 insertions, 0 deletions
diff --git a/SrcShared/Patches/EmPatchModuleSys.cpp b/SrcShared/Patches/EmPatchModuleSys.cpp new file mode 100644 index 0000000..667f786 --- /dev/null +++ b/SrcShared/Patches/EmPatchModuleSys.cpp @@ -0,0 +1,3217 @@ +/* -*- 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 "EmPatchModuleSys.h" + +#include "CGremlinsStubs.h" // StubAppEnqueueKey +#include "DebugMgr.h" // Debug::ConnectedToTCPDebugger +#include "EmFileImport.h" // InstallExgMgrLib +#include "EmEventOutput.h" // EmEventOutput::PoppingUpForm +#include "EmEventPlayback.h" // EmEventPlayback::ReplayingEvents +#include "EmLowMem.h" // EmLowMem::GetEvtMgrIdle, EmLowMem::TrapExists, EmLowMem_SetGlobal, EmLowMem_GetGlobal +#include "EmMemory.h" // CEnableFullAccess, EmMem_memcpy, EmMem_strcpy, EmMem_strcmp +#include "EmPalmFunction.h" // InEggOfInfiniteWisdom +#include "EmPalmOS.h" // EmPalmOS::RememberStackRange +#include "EmPalmStructs.h" // EmAliasErr +#include "EmPatchMgr.h" // PuppetString +#include "EmPatchModule.h" // IntlMgrAvailable +#include "EmPatchState.h" +#include "EmRPC.h" // RPC::SignalWaiters +#include "EmSession.h" // GetDevice +#include "EmSubroutine.h" +#include "ErrorHandling.h" // Errors::SysFatalAlert +#include "Hordes.h" // Hordes::IsOn, Hordes::PostFakeEvent, Hordes::CanSwitchToApp +#include "HostControlPrv.h" // HandleHostControlCall +#include "Logging.h" // LogEvtAddEventToQueue, etc. +#include "Marshal.h" // CALLED_GET_PARAM_STR +#include "MetaMemory.h" // MetaMemory mark functions +#include "Miscellaneous.h" // SetHotSyncUserName, DateToDays, SystemCallContext +#include "Platform.h" // Platform::SndDoCmd, GetString +#include "PreferenceMgr.h" // Preference (kPrefKeyUserName) +#include "Profiling.h" // StDisableAllProfiling +#include "ROMStubs.h" // FtrSet, FtrUnregister, EvtWakeup, ... +#include "SessionFile.h" // SessionFile +#include "SLP.h" // SLP +#include "Startup.h" // Startup::GetAutoLoads +#include "Strings.r.h" // kStr_ values +#include "SystemPacket.h" // SystemPacket::SendMessage + +#include <vector> // vector + +#if PLATFORM_MAC +#include <errno.h> // ENOENT, errno +#include <sys/types.h> // u_short, ssize_t, etc. +#include <sys/socket.h> // sockaddr +#include <sys/errno.h> // Needed for error translation. +#include <sys/time.h> // fd_set +#include <netdb.h> // hostent +#include <unistd.h> // close +#include <sys/filio.h> // FIONBIO +#include <sys/ioctl.h> // ioctl +#include <netinet/in.h> // sockaddr_in +#include <netinet/tcp.h> // TCP_NODELAY +#include <arpa/inet.h> // inet_ntoa +#endif + +#if PLATFORM_UNIX +#include <errno.h> // ENOENT, errno +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> // timeval +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <netdb.h> +#include <unistd.h> // close +#include <arpa/inet.h> // inet_ntoa +#endif + +#include "PalmPack.h" +#define NON_PORTABLE +#include "HwrROMToken.h" // hwrROMTokenIrda +#undef NON_PORTABLE +#include "PalmPackPop.h" + + +// ====================================================================== +// Global Interfaces +// ====================================================================== + + +// ====================================================================== +// Proto patch table for the system functions. This array will be used +// to create a sparse array at runtime. +// ====================================================================== + +ProtoPatchTableEntry gProtoSysPatchTable[] = +{ + {sysTrapBmpCreate, NULL, SysTailpatch::BmpCreate}, + {sysTrapBmpDelete, NULL, SysTailpatch::BmpDelete}, + {sysTrapClipboardGetItem, SysHeadpatch::ClipboardGetItem, NULL}, + {sysTrapDbgMessage, SysHeadpatch::DbgMessage, NULL}, + {sysTrapClipboardAddItem, NULL, SysTailpatch::ClipboardAddItem}, + {sysTrapClipboardAppendItem, NULL, SysTailpatch::ClipboardAppendItem}, + {sysTrapDmCloseDatabase, SysHeadpatch::DmCloseDatabase, NULL}, + {sysTrapDmInit, SysHeadpatch::DmInit, NULL}, + {sysTrapDmGet1Resource, NULL, SysTailpatch::DmGet1Resource}, + {sysTrapDmGetResource, NULL, SysTailpatch::DmGetResource}, + {sysTrapErrDisplayFileLineMsg, SysHeadpatch::ErrDisplayFileLineMsg, NULL}, + {sysTrapEvtAddEventToQueue, SysHeadpatch::EvtAddEventToQueue, NULL}, + {sysTrapEvtAddUniqueEventToQueue,SysHeadpatch::EvtAddUniqueEventToQueue,NULL}, + {sysTrapEvtEnqueueKey, SysHeadpatch::EvtEnqueueKey, NULL}, + {sysTrapEvtEnqueuePenPoint, SysHeadpatch::EvtEnqueuePenPoint, NULL}, + {sysTrapEvtGetEvent, SysHeadpatch::RecordTrapNumber, SysTailpatch::EvtGetEvent}, + {sysTrapEvtGetPen, SysHeadpatch::RecordTrapNumber, SysTailpatch::EvtGetPen}, + {sysTrapEvtGetSysEvent, NULL, SysTailpatch::EvtGetSysEvent}, + {sysTrapEvtSysEventAvail, NULL, SysTailpatch::EvtSysEventAvail}, + {sysTrapExgReceive, NULL, SysTailpatch::ExgReceive}, + {sysTrapExgSend, NULL, SysTailpatch::ExgSend}, + {sysTrapExgDoDialog, SysHeadpatch::ExgDoDialog, NULL}, + {sysTrapFrmCustomAlert, SysHeadpatch::FrmCustomAlert, NULL}, + {sysTrapFrmDrawForm, SysHeadpatch::FrmDrawForm, NULL}, + {sysTrapFrmPopupForm, SysHeadpatch::FrmPopupForm, NULL}, + {sysTrapFtrInit, NULL, SysTailpatch::FtrInit}, + {sysTrapFtrSet, NULL, SysTailpatch::FtrSet}, + {sysTrapHostControl, SysHeadpatch::HostControl, NULL}, + {sysTrapHwrBatteryLevel, SysHeadpatch::HwrBatteryLevel, NULL}, + {sysTrapHwrBattery, SysHeadpatch::HwrBattery, NULL}, + {sysTrapHwrDockStatus, SysHeadpatch::HwrDockStatus, NULL}, + {sysTrapHwrGetROMToken, SysHeadpatch::HwrGetROMToken, NULL}, + {sysTrapHwrMemReadable, NULL, SysTailpatch::HwrMemReadable}, + {sysTrapHwrSleep, SysHeadpatch::HwrSleep, SysTailpatch::HwrSleep}, + {sysTrapPenOpen, SysHeadpatch::PenOpen, NULL}, + {sysTrapPrefSetAppPreferences, SysHeadpatch::PrefSetAppPreferences, NULL}, + {sysTrapSndDoCmd, SysHeadpatch::SndDoCmd, NULL}, + {sysTrapSysAppExit, SysHeadpatch::SysAppExit, NULL}, + {sysTrapSysAppLaunch, SysHeadpatch::SysAppLaunch, NULL}, + {sysTrapSysAppStartup, NULL, SysTailpatch::SysAppStartup}, + {sysTrapSysBinarySearch, SysHeadpatch::SysBinarySearch, SysTailpatch::SysBinarySearch}, + {sysTrapSysEvGroupWait, SysHeadpatch::SysEvGroupWait, NULL}, + {sysTrapSysFatalAlert, SysHeadpatch::SysFatalAlert, NULL}, + {sysTrapSysLaunchConsole, SysHeadpatch::SysLaunchConsole, NULL}, + {sysTrapSysSemaphoreWait, SysHeadpatch::SysSemaphoreWait, NULL}, + {sysTrapSysTaskCreate, NULL, SysTailpatch::SysTaskCreate}, + {sysTrapSysUIAppSwitch, SysHeadpatch::SysUIAppSwitch, NULL}, + {sysTrapTblHandleEvent, SysHeadpatch::TblHandleEvent, SysTailpatch::TblHandleEvent}, + {sysTrapTimInit, NULL, SysTailpatch::TimInit}, + {sysTrapUIInitialize, NULL, SysTailpatch::UIInitialize}, + {sysTrapUIReset, NULL, SysTailpatch::UIReset}, + + {sysTrapCtlNewControl, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + {sysTrapFldNewField, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + {sysTrapFrmInitForm, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + {sysTrapFrmNewBitmap, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + {sysTrapFrmNewGadget, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + {sysTrapFrmNewGsi, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + {sysTrapFrmNewLabel, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + {sysTrapLstNewList, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + {sysTrapWinAddWindow, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + {sysTrapWinRemoveWindow, SysHeadpatch::UnmarkUIObjects, SysTailpatch::MarkUIObjects}, + + {0, NULL, NULL} +}; + + +extern ProtoPatchTableEntry gProtoMemMgrPatchTable[]; + + + + + +// =========================================================================== +// ¥ +// =========================================================================== + +// ====================================================================== +// Globals and constants +// ====================================================================== + + +static long gSaveDrawStateStackLevel; + +static Bool gDontPatchClipboardAddItem; +static Bool gDontPatchClipboardGetItem; + + +// ====================================================================== +// Private functions +// ====================================================================== + +static long PrvGetDrawStateStackLevel (void); +static void PrvCopyPalmClipboardToHost (void); +static void PrvCopyHostClipboardToPalm (void); + +void PrvAutoload (void); // Also called in PostLoad +void PrvSetCurrentDate (void); // Also called in PostLoad + + +#pragma mark - + + + +// =========================================================================== +// ¥ EmPatchModuleSys +// =========================================================================== + +/*********************************************************************** + * + * FUNCTION: EmPatchModuleSys::EmPatchModuleSys + * + * DESCRIPTION: Constructor + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +EmPatchModuleSys::EmPatchModuleSys() : + EmPatchModule ("~system", gProtoSysPatchTable, gProtoMemMgrPatchTable) +{ +} + + +// =========================================================================== +// ¥ SysHeadpatch +// =========================================================================== + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::RecordTrapNumber + * + * DESCRIPTION: Record the trap we're executing for our patch to + * SysEvGroupWait later. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::RecordTrapNumber (void) +{ + EmAssert (gCPU); + uint8* realMem = EmMemGetRealAddress (gCPU->GetPC ()); + + EmAssert (EmMemDoGet16 (realMem - 2) == (m68kTrapInstr + sysDispatchTrapNum)); + + EmPatchState::SetLastEvtTrap (EmMemDoGet16 (realMem)); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::ClipboardGetItem + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::ClipboardGetItem (void) +{ + if (!Hordes::IsOn () && !gDontPatchClipboardGetItem) + { + ::PrvCopyHostClipboardToPalm (); + } + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::UnmarkUIObjects + * + * DESCRIPTION: . + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::UnmarkUIObjects (void) +{ + MetaMemory::UnmarkUIObjects (); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::DbgMessage + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::DbgMessage (void) +{ + // void DbgMessage(const Char* aStr); + + CALLED_SETUP ("void", "const Char* aStr"); + + CALLED_GET_PARAM_STR (Char, aStr); + + if (aStr != EmMemNULL) + { + // Get the string that's passed in. + + string msgCopy (aStr); + CSocket* debuggerSocket = Debug::GetDebuggerSocket (); + Bool contactedDebugger = false; + + // If we're connected to a debugger, try to send it the string. + + if (debuggerSocket) + { + SLP slp (debuggerSocket); + ErrCode err = SystemPacket::SendMessage (slp, msgCopy.c_str ()); + if (!err) + { + contactedDebugger = true; + } + } + + // If that failed or if we're not connected to a debugger, + // tell the user in one of our own dialogs. + + if (!contactedDebugger) + { + // Squelch these debugger messages. Some functions in the ROM + // (see Content.c and Progress.c) use DbgMessage for logging + // instead of debugging. I'm hoping this will get fixed after + // Palm OS 4.0, so I'm only checking in versions before that. + // + // ("Transaction finished" actually appears only in 3.2 and + // 3.3 ROMs, so that one's already taken care of.) + // + // Also note that I have the last character as "\x0A". In + // the ROM sources, this is "\n". However, the value that + // that turns into is compiler-dependent, so I'm using the + // value that the Palm compiler is currently known to use. + + if ((msgCopy != "...Transaction cancelled\x0A" && + msgCopy != "Transaction finished\x0A" && + msgCopy != "c") || + EmPatchState::OSMajorMinorVersion () > 40) + { + Errors::ReportErrDbgMessage (msgCopy.c_str ()); + } + } + } + + return kSkipROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::DmCloseDatabase + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::DmCloseDatabase (void) +{ + // Err DmCloseDatabase(DmOpenRef dbR) + + CALLED_SETUP ("Err", "DmOpenRef dbR"); + + CALLED_GET_PARAM_VAL (DmOpenRef, dbR); + + // Allow for a NULL reference. Applications shouldn't be doing + // this, but the test harness does in order to make sure the + // OS recovers OK. We need to check for it specially, because + // even though DmCloseDatabase checks for and handles the NULL + // reference, we're inserting a call to DmOpenDatabaseInfo here, + // which does NOT handle the NULL reference (it will call + // ErrDisplay, but subsequent code is not defensive and will crash). + + if (dbR == NULL) + return kExecuteROM; + + UInt16 openCount; + Boolean resDB; + + Err err = ::DmOpenDatabaseInfo ( + dbR, // DmOpenRef dbR, + NULL, // LocalID* dbIDP, + &openCount, // UInt16 * openCountP, + NULL, // UInt16 * modeP, + NULL, // UInt16 * cardNoP, + &resDB); // Boolean * resDBP) + + if (!err && resDB && openCount == 1) + { + MemHandle resource; + UInt16 ii; + UInt16 numResources = ::DmNumResources (dbR); + + for (ii = 0; ii < numResources; ++ii) + { + resource = ::DmGetResourceIndex (dbR, ii); + MetaMemory::UnregisterBitmapHandle (resource); + } + + // Search for any overlay databases and unregister any + // bitmaps they may have, too. + // + // Overlays were added in Palm OS 3.5; don't check the + // "openType" field in older OSes. + + if (EmPatchState::OSMajorMinorVersion () >= 35) + { + emuptr dbAccessP = (emuptr) (DmOpenRef) dbR; + EmAliasDmAccessType<PAS> dbAccess (dbAccessP); + + // If this is a "base" database, look for a corresponding + // overlay database. Do this by iterating over the list + // of open databases and finding the one in the list + // preceding the base database we're closing. + + if (dbAccess.openType == openTypeBase) + { + // Get the first open database. + + DmOpenRef olRef = ::DmNextOpenDatabase (NULL); + + // Iterate over the open databases until we get to the end + // or until we meet up with then one we're closing. The + // overlay database will appear in the linked list *before* + // the one we're closing, so if we get to that one without + // finding the overlay, we never will find it. + + while (olRef && olRef != dbR) + { + // For each open database, see if it's an overlay type. + // If it is, see if the "next" field points to the database + // we're closing. + + emuptr olAccessP = (emuptr) olRef; + EmAliasDmAccessType<PAS> olAccess (olAccessP); + + UInt8 openType = olAccess.openType; + emuptr next = olAccess.next; + + if (openType == openTypeOverlay && next == dbAccessP) + { + // OK, now that we're here, let's iterate over + // the database and release any resources it + // has, too. + + numResources = ::DmNumResources (olRef); + for (ii = 0; ii < numResources; ++ii) + { + resource = ::DmGetResourceIndex (olRef, ii); + MetaMemory::UnregisterBitmapHandle (resource); + } + + break; // Break out of the "while (olRef && olRef != dbR)..." loop. + } + + // This either wasn't an overlay database, or it didn't + // belong to the base database we were closing. Move + // on to the next database. + + olRef = ::DmNextOpenDatabase (olRef); + } + + // Make sure we found the overlay. + + EmAssert (olRef && olRef != dbR); + } + } + } + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::DmInit + * + * DESCRIPTION: After MemInit is called, we need to sync up with the + * initial state of the heap(s). However, MemInit is not + * called via the trap table, so we can't easily tailpatch + * it. DmInit is the first such function called after + * MemInit, so we headpatch *it* instead of tailpatching + * MemInit. + * + * (Actually, MemHeapCompact is called as one of the last + * things MemInit does which makes it an interesting + * candidate for patching in order to sync up with the + * heap state. However, if we were to do a full sync on + * that call, a full sync would occur on *every* call to + * MemHeapCompact, which we don't really want to do.) + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::DmInit (void) +{ +// MetaMemory::SyncAllHeaps (); + + EmPatchState::SetHeapInitialized (true); + + // If they haven't been released by now, then release the boot keys. + + gSession->ReleaseBootKeys (); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::ErrDisplayFileLineMsg + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +typedef Bool (*VersionChecker)(void); +typedef Bool (*FunctionChecker)(emuptr addr); + +struct EmInvalidErrorMessageData +{ + VersionChecker fVersionChecker; + FunctionChecker fFunctionChecker; + const char* fMessage; +}; + +EmInvalidErrorMessageData kInvalidErrorMessages [] = +{ + { + &EmPatchState::HasECValidateFieldBug, + &::InECValidateField, + "Invalid insertion point position" + }, + { + &EmPatchState::HasPrvDrawSliderControlBug, + &::InPrvDrawSliderControl, + "Background must be at least half as wide as slider." + }, + { + NULL, // Don't care about the system version. + &::InPrvFindMemoryLeaks, + NULL // Don't care about the actual text. + } +}; + + +CallROMType SysHeadpatch::ErrDisplayFileLineMsg (void) +{ + // void ErrDisplayFileLineMsg(CharPtr filename, UInt16 lineno, CharPtr msg) + + CALLED_SETUP ("void", "CharPtr filename, UInt16 lineno, CharPtr msg"); + + CALLED_GET_PARAM_STR (Char, msg); + + { + CEnableFullAccess munge; // Remove blocks on memory access. + + // Force this guy to true. If it's false, ErrDisplayFileLineMsg will + // just try to enter the debugger. + + UInt16 sysMiscFlags = EmLowMem_GetGlobal (sysMiscFlags); + EmLowMem_SetGlobal (sysMiscFlags, sysMiscFlags | sysMiscFlagUIInitialized); + + // Clear this low-memory flag so that we force the dialog to display. + // If this flag is true, ErrDisplayFileLineMsg will just try to enter + // the debugger. + + EmLowMem_SetGlobal (dbgWasEntered, false); + } + + // Some ROMs incorrectly display error messages via ErrDisplayFileLineMsg. + // Check to see if we are running on a ROM version with one of those + // erroneous messages, check to see that we are in the function that + // displays the message, and check to see if the text of the message + // handed to us is one of the incorrect ones. If all conditions are + // true, squelch the message. + + for (size_t ii = 0; ii < countof (kInvalidErrorMessages); ++ii) + { + EmAssert (gCPU); + + EmInvalidErrorMessageData* d = &kInvalidErrorMessages[ii]; + + if ( + (!d->fVersionChecker || d->fVersionChecker ()) && + (!d->fFunctionChecker || d->fFunctionChecker (gCPU->GetPC ()))) + { + if (!d->fMessage || (strcmp (msg, d->fMessage) == 0)) + { + return kSkipROM; + } + } + } + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::EvtAddEventToQueue + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::EvtAddEventToQueue (void) +{ + // void EvtAddEventToQueue (const EventPtr event) + + CALLED_SETUP ("void", "const EventPtr event"); + + CALLED_GET_PARAM_REF (EventType, event, Marshal::kInput); + + LogEvtAddEventToQueue (*event); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::EvtAddUniqueEventToQueue + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::EvtAddUniqueEventToQueue (void) +{ + // void EvtAddUniqueEventToQueue(const EventPtr eventP, const UInt32 id, const Boolean inPlace) + + CALLED_SETUP ("void", "const EventPtr eventP, const UInt32 id, const Boolean inPlace"); + + CALLED_GET_PARAM_REF (EventType, eventP, Marshal::kInput); + CALLED_GET_PARAM_VAL (UInt32, id); + CALLED_GET_PARAM_VAL (Boolean, inPlace); + + LogEvtAddUniqueEventToQueue (*eventP, id, inPlace); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::EvtEnqueueKey + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::EvtEnqueueKey (void) +{ + // Err EvtEnqueueKey(UInt16 ascii, UInt16 keycode, UInt16 modifiers) + + CALLED_SETUP ("Err", "UInt16 ascii, UInt16 keycode, UInt16 modifiers"); + + CALLED_GET_PARAM_VAL (UInt16, ascii); + CALLED_GET_PARAM_VAL (UInt16, keycode); + CALLED_GET_PARAM_VAL (UInt16, modifiers); + + LogEvtEnqueueKey (ascii, keycode, modifiers); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::EvtEnqueuePenPoint + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::EvtEnqueuePenPoint (void) +{ + // Err EvtEnqueuePenPoint(PointType* ptP) + + CALLED_SETUP ("Err", "PointType* ptP"); + + CALLED_GET_PARAM_REF (PointType, ptP, Marshal::kInput); + + LogEvtEnqueuePenPoint (*ptP); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::ExgDoDialog + * + * DESCRIPTION: Always accept the beam if we're beaming it in via our + * special ExgMgr "driver". + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::ExgDoDialog (void) +{ + // Boolean ExgDoDialog(ExgSocketPtr socketP, ExgDialogInfoType *infoP, Err *errP) + + CALLED_SETUP ("Boolean", "ExgSocketPtr socketP, ExgDialogInfoType *infoP, Err *errP"); + + CALLED_GET_PARAM_VAL (ExgSocketPtr, socketP); + CALLED_GET_PARAM_REF (Err, errP, Marshal::kInOut); + + if (!EmPatchState::GetAutoAcceptBeamDialogs()) + return kExecuteROM; + + if (!socketP) + return kExecuteROM; + + CALLED_PUT_PARAM_REF (errP); + PUT_RESULT_VAL (Boolean, true); + + return kSkipROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::FrmCustomAlert + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +#define replaceBeamAppAlert 2008 +#define beamReplaceErrorAppIsRunning 2012 + +#define replaceBeamAppAlertYesButton 0 + +CallROMType SysHeadpatch::FrmCustomAlert (void) +{ + // UInt16 FrmCustomAlert (UInt16 alertId, const Char* s1, const Char* s2, const Char* s3) + + CALLED_SETUP ("UInt16", "UInt16 alertId, const Char* s1, const Char* s2, const Char* s3"); + + CALLED_GET_PARAM_VAL (UInt16, alertId); + + if (!EmPatchState::GetAutoAcceptBeamDialogs()) + return kExecuteROM; + + // "App already exists, replace it?" + + if (alertId == replaceBeamAppAlert) + { + PUT_RESULT_VAL (UInt16, replaceBeamAppAlertYesButton); + return kSkipROM; + } + + // "App is running. Switch first." + + if (alertId == beamReplaceErrorAppIsRunning) + { + PUT_RESULT_VAL (UInt16, 0); // Can be anything. + return kSkipROM; + } + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::FrmDrawForm + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::FrmDrawForm (void) +{ + // void FrmDrawForm (const FormPtr frm) + + CALLED_SETUP ("void", "const FormPtr frm"); + + CALLED_GET_PARAM_VAL (FormPtr, frm); + + ::ValidateFormObjects (frm); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::FrmPopupForm + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::FrmPopupForm (void) +{ + // void FrmPopupForm (UInt16 formId) + +// CALLED_SETUP ("void", "UInt16 formId"); + +// CALLED_GET_PARAM_VAL (UInt16, formId); + + EmEventOutput::PoppingUpForm (); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::HostControl + * + * DESCRIPTION: This one's kind of odd. Originally, there was + * SysGremlins, which was declared as follows: + * + * UInt32 SysGremlins(GremlinFunctionType selector, + * GremlinParamsType *params) + * + * Also originally, the only defined selector was + * GremlinIsOn. + * + * Now, SysGremlins is extended to be SysHostControl, + * which allows the Palm environment to access host + * functions if it's actually running under the simulator + * or emulator. + * + * Because of this extension, functions implemented via + * this trap are not limited to pushing a selector and + * parameter block on the stack. Now, they will all push + * on a selector, but what comes after is dependent on the + * selector. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::HostControl (void) +{ + return HandleHostControlCall (); +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::HwrBatteryLevel + * + * DESCRIPTION: Return that the battery is always full. HwrBatteryLevel + * is the bottleneck function called to determine the + * battery level. By patching it this way, we don't have + * to emulate the hardware registers that report the + * battery level. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::HwrBatteryLevel (void) +{ + // On non-328 devices, we emulate the hardware that returns this + // information, so we don't need to patch this function. + + // We don't currently emulate the Prism battery hardware, so we + // allow the patch. Not sure if this is called by the Prism ROM, + // but we patch it to be safe (better than dividing by zero). + + EmAssert (gSession); + + if (!gSession->GetDevice().Supports68328 () && + gSession->GetDevice().HardwareID () != 0x0a /*halModelIDVisorPrism*/) + { + return kExecuteROM; + } + + // UInt16 HwrBatteryLevel(void) + + CALLED_SETUP ("UInt16", "void"); + + PUT_RESULT_VAL (UInt16, 255); // Hardcode a maximum level + + return kSkipROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::HwrBattery + * + * DESCRIPTION: If queried for the battery level, return that the battery + * is always full. This is equivalent to the HwrBatteryLevel + * patch, necessary because some newer devices call HwrBattery + * for this information. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + * History: + * 2000-05-10 Added by Bob Petersen + * + ***********************************************************************/ + +CallROMType SysHeadpatch::HwrBattery (void) +{ + // On non-328 devices, we emulate the hardware that returns this + // information, so we don't need to patch this function. + + // We don't currently emulate the Prism battery hardware, so we + // allow the patch. + + EmAssert (gSession); + + if (!gSession->GetDevice().Supports68328 () && + gSession->GetDevice().HardwareID () != 0x0a /*halModelIDVisorPrism*/) + { + return kExecuteROM; + } + + // Err HwrBattery(UInt16 /* HwrBatterCmdEnum*/ cmd, void * cmdP) + + CALLED_SETUP ("Err", "UInt16 cmd, void * cmdP"); + + CALLED_GET_PARAM_VAL (UInt16, cmd); + + if (cmd == 2 /* hwrBatteryCmdMainRead */) + { + CALLED_GET_PARAM_REF (HwrBatCmdReadType, cmdP, Marshal::kInOut); + + if (gSession->GetDevice().HardwareID () == 0x0a /*halModelIDVisorPrism*/) + { + // MAINTAINER'S NOTE: The following code and comment are pretty + // much what I got from Handspring. The comment says 4.2 volts, + // and the code contains redundant assignments that first assign + // 4.2 volts and then 4.0 volts. I'm just keeping this in case + // they really want it this way for some reason. + + // DOLATER: Battery voltage should differ by battery type. + // 4.2 is returned to handle lithium ion batteries. 'mVolts' + // is the value used by the Prism display, not 'abs'. + (*cmdP).mVolts = 4200; // 4.2 volts + (*cmdP).mVolts = 4000; // 4.0 volts + } + else + { + (*cmdP).mVolts = 2500; // 2.5 volts + } + + (*cmdP).abs = 255; // Hardcode a maximum level + + cmdP.Put (); + + PUT_RESULT_VAL (Err, errNone); + return kSkipROM; + } + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::HwrDockStatus + * + * DESCRIPTION: Always return hwrDockStatusUsingExternalPower. We + * could fake this out by twiddling the right bits in the + * Dragonball and DragonballEZ emulation units, but those + * bits are different for almost every device. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::HwrDockStatus (void) +{ + // On non-328 devices, we emulate the hardware that returns this + // information, so we don't need to patch this function. + + EmAssert (gSession); + + if (!gSession->GetDevice().Supports68328 ()) + { + return kExecuteROM; + } + + // hwrDockStatusState HwrDockStatus(void) + // + // (added in Palm OS 3.1) + // (changed later to return UInt16) + + CALLED_SETUP ("UInt16", "void"); + + // Old enumerated values from Hardware.h: + // + // DockStatusNotDocked = 0, + // DockStatusInModem, + // DockStatusInCharger, + // DockStatusUnknown = 0xFF + + // New defines from HwrDock.h +#define hwrDockStatusUndocked 0x0000 // nothing is attached +#define hwrDockStatusModemAttached 0x0001 // some type of modem is attached +#define hwrDockStatusDockAttached 0x0002 // some type of dock is attached +#define hwrDockStatusUsingExternalPower 0x0004 // using some type of external power source +#define hwrDockStatusCharging 0x0008 // internal power cells are recharging + + PUT_RESULT_VAL (UInt16, hwrDockStatusUsingExternalPower); + + return kSkipROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::HwrGetROMToken + * + * DESCRIPTION: Patch this guy so that we never return the 'irda' token. + * We should take this out when some sort of IR support is + * added. + * + * NOTE: This patch is useless for diverting the ROM. It + * calls HwrGetROMToken directly, which means that it will + * bypass this patch. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::HwrGetROMToken (void) +{ + // Err HwrGetROMToken (UInt16 cardNo, UInt32 token, UInt8** dataP, UInt16* sizeP) + + CALLED_SETUP ("Err", "UInt16 cardNo, UInt32 token, UInt8** dataP, UInt16* sizeP"); + + CALLED_GET_PARAM_VAL (UInt16, cardNo); + CALLED_GET_PARAM_VAL (UInt32, token); + CALLED_GET_PARAM_REF (UInt8Ptr, dataP, Marshal::kInOut); + CALLED_GET_PARAM_REF (UInt16, sizeP, Marshal::kInOut); + + if (cardNo == 0 && token == hwrROMTokenIrda) + { + if (dataP) + { + *dataP = 0; + dataP.Put (); + } + + if (sizeP) + { + *sizeP = 0; + sizeP.Put (); + } + + PUT_RESULT_VAL (Err, ~0); // token not found. + + return kSkipROM; + } + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::HwrSleep + * + * DESCRIPTION: Record whether or not we are sleeping and update the + * boolean that determines if low-memory access is OK. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::HwrSleep (void) +{ + // void HwrSleep(Boolean untilReset, Boolean emergency) + + // HwrSleep changes the exception vectors for for the interrupts, + // so temporarily unlock those. We'll re-establish them in the + // HwrSleep tailpatch. + + MetaMemory::MarkTotalAccess (offsetof (M68KExcTableType, busErr), + offsetof (M68KExcTableType, busErr) + sizeof (emuptr)); + + MetaMemory::MarkTotalAccess (offsetof (M68KExcTableType, addressErr), + offsetof (M68KExcTableType, addressErr) + sizeof (emuptr)); + + MetaMemory::MarkTotalAccess (offsetof (M68KExcTableType, illegalInstr), + offsetof (M68KExcTableType, illegalInstr) + sizeof (emuptr)); + + MetaMemory::MarkTotalAccess (offsetof (M68KExcTableType, autoVec1), + offsetof (M68KExcTableType, trapN[0])); + + // On Palm OS 1.0, there was code in HwrSleep that would execute only if + // memory location 0xC2 was set. It looks like debugging code (that is, + // Ron could change it from the debugger to try different things out), + // but we still have to allow access to it. + + if (EmPatchState::OSMajorVersion () == 1) + { + MetaMemory::MarkTotalAccess (0x00C2, 0x00C3); + } + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::KeyCurrentState + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +// From Roger: +// +// I was thinking a bit more about Gremlins and games yesterday. Games which +// use the buttons as input have been a special case for Gremlins because +// Gremlins only faked events and pen points. Normally games have to fake +// their own button mask, and they get better results if have some buttons +// held down more often than others. +// +// Now I'm thinking different. With Poser, the KeyCurrentState call should +// be stolen when Gremlins is running. All of the keys possible should have +// their button bits on half the time. This will allow users to test games. +// By not tuning how often buttons should be held down, the testing process +// will take longer to excerise all app functionality, but it's better than +// now. App developers can override the default Gremlin values with their +// own for better results. +// +// To successfully test this, A game like SubHunt should play on it's own for +// a least a while. HardBall is an example of a game which would really +// benefit from recognizing Gremlins is running and tune itself to make the +// testing more effective. It should grant infinite balls until after the +// last level is finished. +// +// I actually think this is important enough to be for Acorn because it +// enables users to test a large class of apps which otherwise can't. I +// think it's easy to implement. Basically just have KeyCurrentState return +// the int from the random number generator. Each bit should be on about +// half the time. +// +// Follow-up commentary: it turns out that this patch is not having the +// effect we hoped. SubHunt was so overwhelmed with events from Gremlins +// that it rarely had the chance to call KeyCurrentState. We're thinking +// of Gremlins backing off on posting events if the SysGetEvent sleep time +// is small (i.e., not "forever"), but we'll have to think about the impact +// on other apps first. + +#if 0 +CallROMType SysHeadpatch::KeyCurrentState (void) +{ + // UInt32 KeyCurrentState(void) + + CALLED_SETUP ("UInt32", "void"); + + // Remove this for now. Its current implementation uses the Std C Lib + // random number generator, which is not in sync with the Gremlins RNG. + + if (Hordes::IsOn ()) + { + // Let's try setting each bit 1/4 of the time. + + uint32 bits = rand () & rand (); + + PUT_RESULT_VAL (Uint32, bits); + + return kSkipROM; + } + + return kExecuteROM; +} +#endif + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::PenOpen + * + * DESCRIPTION: This is where the pen calibration information is read. + * Preflight this call to add the calibration information + * to the preferences database if it doesn't exist. That + * way, we don't have to continually calibrate the screen + * when we boot up. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::PenOpen (void) +{ + // Err PenOpen(void) + + ::InstallCalibrationInfo (); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::PrefSetAppPreferences + * + * DESCRIPTION: Change the default proxy server address. If it looks + * like INet is establishing the old proxy server address, + * substitute the current one instead. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::PrefSetAppPreferences (void) +{ + // void PrefSetAppPreferences (UInt32 creator, UInt16 id, Int16 version, + // const void *prefs, UInt16 prefsSize, Boolean saved) + + CALLED_SETUP ("void", "UInt32 creator, UInt16 id, Int16 version, " + "const void *prefs, UInt16 prefsSize, Boolean saved"); + + CALLED_GET_PARAM_VAL (UInt32, creator); + CALLED_GET_PARAM_VAL (emuptr, prefs); + CALLED_GET_PARAM_VAL (UInt16, prefsSize); + CALLED_GET_PARAM_VAL (Boolean, saved); + +#define inetCreator 'inet' + + if ((creator == inetCreator) && saved && (prefsSize >= 3 + 64)) + { + emuptr proxyP = prefs + 3; + + if ((EmMem_strcmp (proxyP, "207.240.80.136") == 0) || + (EmMem_strcmp (proxyP, "209.247.202.106") == 0)) + { + static string currentIPAddress; + + // See if we've looked up the address, yet. + + if (currentIPAddress.empty ()) + { + // If not, get the host information. + + struct hostent* host = gethostbyname ("content-dev.palm.net"); + if (!(host && host->h_addrtype == AF_INET)) + { + host = gethostbyname ("content-dev2.palm.net"); + } + + if (host && host->h_addrtype == AF_INET) + { + // If the address family looks like one we can handle, + // get and use the first one. + + struct in_addr* addr_in = (struct in_addr*) host->h_addr_list[0]; + if (addr_in) + { + char* as_string = inet_ntoa (*addr_in); + currentIPAddress = as_string; + } + } + } + + // If we have the address cached NOW, use it to replace + // the hardcoded addresses. + + if (!currentIPAddress.empty ()) + { + EmMem_strcpy (proxyP, currentIPAddress.c_str ()); + } + } + } + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::SndDoCmd + * + * DESCRIPTION: Intercept calls to the Sound Manager and generate the + * equivalent host commands. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::SndDoCmd (void) +{ + Preference<bool> pref (kPrefKeyEnableSounds); + + if (!*pref) + return kExecuteROM; + + // Err SndDoCmd(void * chanP, SndCommandPtr cmdP, Boolean noWait) + + CALLED_SETUP ("Err", "void * chanP, SndCommandPtr cmdP, Boolean noWait"); + + CALLED_GET_PARAM_REF (SndCommandType, cmdP, Marshal::kInput); + + PUT_RESULT_VAL (Err, errNone); // Set default return value + + return Platform::SndDoCmd (*cmdP); +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::SysAppExit + * + * DESCRIPTION: If the application calling SysAppExit was launched as a + * full application, then "forget" any information we have + * about it. When the next application is launched, we'll + * collect information on it in SysAppStartup. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::SysAppExit (void) +{ + // Err SysAppExit(SysAppInfoPtr appInfoP, MemPtr prevGlobalsP, MemPtr globalsP) + + CALLED_SETUP ("Err", "SysAppInfoPtr appInfoP, MemPtr prevGlobalsP, MemPtr globalsP"); + + CALLED_GET_PARAM_REF (SysAppInfoType, appInfoP, Marshal::kInput); + + if (appInfoP == NULL) + return kExecuteROM; + + Int16 cmd = (*appInfoP).cmd; + UInt16 memOwnerID = (*appInfoP).memOwnerID; + UInt16 launchFlags = (*appInfoP).launchFlags; + + if (false /*LogLaunchCodes ()*/) + { + emuptr dbP = (emuptr) ((*appInfoP).dbP); + emuptr openP = EmMemGet32 (dbP + offsetof (DmAccessType, openP)); + LocalID dbID = EmMemGet32 (openP + offsetof (DmOpenInfoType, hdrID)); + UInt16 cardNo = EmMemGet16 (openP + offsetof (DmOpenInfoType, cardNo)); + + char name[dmDBNameLength] = {0}; + UInt32 type = 0; + UInt32 creator = 0; + + /* Err err =*/ ::DmDatabaseInfo ( + cardNo, dbID, name, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + &type, &creator); + + LogAppendMsg ("SysAppExit called:"); + LogAppendMsg (" cardNo: %ld", (long) cardNo); + LogAppendMsg (" dbID: 0x%08lX", (long) dbID); + LogAppendMsg (" name: %s", name); + LogAppendMsg (" type: %04lX", type); + LogAppendMsg (" creator: %04lX", creator); + } + + if (cmd == sysAppLaunchCmdNormalLaunch) + { + EmuAppInfo appInfo; + EmPatchState::CollectCurrentAppInfo ((emuptr) appInfoP, appInfo); + + if (appInfo.fCardNo == EmPatchState::GetQuitAppCardNo () && appInfo.fDBID == EmPatchState::GetQuitAppDbID ()) + { + EmPatchState::SetTimeToQuit (); + } + } + + // Go through and dispose of any memory chunks allocated by this application. + // <chg 5-8-98 RM> Changed test to: launchFlags & sysAppLaunchFlagNewGlobals + // from rootP==NULL so that it works correcty for sublaunched apps + // that get their own globals. + + if (memOwnerID && (launchFlags & sysAppLaunchFlagNewGlobals)) + { + ::CheckForMemoryLeaks (memOwnerID); + } + + EmPatchState::RemoveCurAppInfo (); // !!! should probably make sure appInfoP matches + // the top guy on the stack. + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::SysAppLaunch + * + * DESCRIPTION: Log information app launches and action codes. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::SysAppLaunch (void) +{ + // Err SysAppLaunch(UInt16 cardNo, LocalID dbID, UInt16 launchFlags, + // UInt16 cmd, MemPtr cmdPBP, UInt32* resultP) + + CALLED_SETUP ("Err", "UInt16 cardNo, LocalID dbID, UInt16 launchFlags," + "UInt16 cmd, MemPtr cmdPBP, UInt32* resultP"); + + CALLED_GET_PARAM_VAL (UInt16, cardNo); + CALLED_GET_PARAM_VAL (LocalID, dbID); + CALLED_GET_PARAM_VAL (UInt16, launchFlags); + CALLED_GET_PARAM_VAL (UInt16, cmd); + + if (false /*LogLaunchCodes ()*/) + { + const char* launchStr = ::LaunchCmdToString (cmd); + + char name[dmDBNameLength] = {0}; + UInt32 type = 0; + UInt32 creator = 0; + + /* Err err =*/ ::DmDatabaseInfo ( + cardNo, dbID, name, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + &type, &creator); + + LogAppendMsg ("SysAppLaunch called:"); + LogAppendMsg (" cardNo: %ld", (long) cardNo); + LogAppendMsg (" dbID: 0x%08lX", (long) dbID); + LogAppendMsg (" name: %s", name); + LogAppendMsg (" type: %04lX", type); + LogAppendMsg (" creator: %04lX", creator); + LogAppendMsg (" launchFlags: 0x%08lX", (long) launchFlags); + LogAppendMsg (" cmd: %ld (%s)", (long) cmd, launchStr); + +#if 0 + switch (cmd) + { + case sysAppLaunchCmdNormalLaunch: + // No parameter block + break; + + case sysAppLaunchCmdFind: + { + FindParamsType parms; + + LogAppendMsg (" FindParamsType:"); + LogAppendMsg (" dbAccesMode: %ld", (long) parms.dbAccesMode); + LogAppendMsg (" recordNum: %ld", (long) parms.recordNum); + LogAppendMsg (" more: %ld", (long) parms.more); + LogAppendMsg (" strAsTyped: %ld", (long) parms.strAsTyped); + LogAppendMsg (" strToFind: %ld", (long) parms.strToFind); + LogAppendMsg (" numMatches: %ld", (long) parms.numMatches); + LogAppendMsg (" lineNumber: %ld", (long) parms.lineNumber); + LogAppendMsg (" continuation: %ld", (long) parms.continuation); + LogAppendMsg (" searchedCaller: %ld", (long) parms.searchedCaller); + LogAppendMsg (" callerAppDbID: %ld", (long) parms.callerAppDbID); + LogAppendMsg (" callerAppCardNo: %ld", (long) parms.callerAppCardNo); + LogAppendMsg (" appDbID: %ld", (long) parms.appCardNo); + LogAppendMsg (" newSearch: %ld", (long) parms.newSearch); + LogAppendMsg (" searchState: %ld", (long) parms.searchState); + LogAppendMsg (" match: %ld", (long) parms.match); + + break; + } + + case sysAppLaunchCmdGoTo: + // GoToParamsType + break; + + case sysAppLaunchCmdSyncNotify: + // No parameter block + break; + + case sysAppLaunchCmdTimeChange: + // No parameter block + break; + + case sysAppLaunchCmdSystemReset: + { + // SysAppLaunchCmdSystemResetType + SysAppLaunchCmdSystemResetType parms; + LogAppendMsg (" SysAppLaunchCmdSystemResetType:"); + LogAppendMsg (" hardReset: %s", parms.hardReset ? "TRUE" : "FALSE"); + LogAppendMsg (" createDefaultDB: %s", parms.createDefaultDB ? "TRUE" : "FALSE"); + break; + } + + case sysAppLaunchCmdAlarmTriggered: + // SysAlarmTriggeredParamType + break; + + case sysAppLaunchCmdDisplayAlarm: + // SysDisplayAlarmParamType + break; + + case sysAppLaunchCmdCountryChange: + // Not sent? + break; + + case sysAppLaunchCmdSyncRequestLocal: +// case sysAppLaunchCmdSyncRequest: + // No parameter block (I think...) + break; + + case sysAppLaunchCmdSaveData: + // SysAppLaunchCmdSaveDataType + break; + + case sysAppLaunchCmdInitDatabase: + // SysAppLaunchCmdInitDatabaseType + break; + + case sysAppLaunchCmdSyncCallApplicationV10: + // SysAppLaunchCmdSyncCallApplicationTypeV10 + break; + + case sysAppLaunchCmdPanelCalledFromApp: + // Panel specific? + // SvcCalledFromAppPBType + // NULL + break; + + case sysAppLaunchCmdReturnFromPanel: + // No parameter block + break; + + case sysAppLaunchCmdLookup: + // App-specific (see AppLaunchCmd.h) + break; + + case sysAppLaunchCmdSystemLock: + // No parameter block + break; + + case sysAppLaunchCmdSyncRequestRemote: + // No parameter block (I think...) + break; + + case sysAppLaunchCmdHandleSyncCallApp: + // SysAppLaunchCmdHandleSyncCallAppType + break; + + case sysAppLaunchCmdAddRecord: + // App-specific (see AppLaunchCmd.h) + break; + + case sysSvcLaunchCmdSetServiceID: + // ServiceIDType + break; + + case sysSvcLaunchCmdGetServiceID: + // ServiceIDType + break; + + case sysSvcLaunchCmdGetServiceList: + // serviceListType + break; + + case sysSvcLaunchCmdGetServiceInfo: + // serviceInfoType + break; + + case sysAppLaunchCmdFailedAppNotify: + // SysAppLaunchCmdFailedAppNotifyType + break; + + case sysAppLaunchCmdEventHook: + // EventType + break; + + case sysAppLaunchCmdExgReceiveData: + // ExgSocketType + break; + + case sysAppLaunchCmdExgAskUser: + // ExgAskParamType + break; + + case sysDialLaunchCmdDial: + // DialLaunchCmdDialType + break; + + case sysDialLaunchCmdHangUp: + // DialLaunchCmdDialType + break; + + case sysSvcLaunchCmdGetQuickEditLabel: + // SvcQuickEditLabelInfoType + break; + + case sysAppLaunchCmdURLParams: + // Part of the URL + break; + + case sysAppLaunchCmdNotify: + // SysNotifyParamType + break; + + case sysAppLaunchCmdOpenDB: + // SysAppLaunchCmdOpenDBType + break; + + case sysAppLaunchCmdAntennaUp: + // No parameter block + break; + + case sysAppLaunchCmdGoToURL: + // URL + break; + } +#endif + } + + // Prevent Symbol applications from running. + + if (cmd == sysAppLaunchCmdSystemReset) + { + UInt32 type; + UInt32 creator; + /*Err err =*/ ::DmDatabaseInfo ( + cardNo, dbID, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + &type, &creator); + + if (type == sysFileTApplication && + (creator == 'SSRA' || creator == 'SYRA')) + { + PUT_RESULT_VAL (Err, errNone); + return kSkipROM; + } + } + + // Work around a bug in Launcher where it tries to send + // sysAppLaunchCmdSyncNotify to any received files that + // aren't PQAs. This code is pretty much the same as + // the fixed version of Launcher. + + static Bool recursing; + + if (!recursing && cmd == sysAppLaunchCmdSyncNotify && EmPatchState::HasSyncNotifyBug ()) + { + UInt32 type; + UInt32 creator; + Err err = ::DmDatabaseInfo ( + cardNo, dbID, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + &type, &creator); + + if (!err) + { + // If it's not an application, then get the application that owns it. + + UInt16 appCardNo = cardNo; + LocalID appDbID = dbID; + + if (type != sysFileTApplication) + { + DmSearchStateType searchState; + + err = ::DmGetNextDatabaseByTypeCreator (true /*new search*/, + &searchState, sysFileTApplication, creator, + true /*latest version*/, &appCardNo, &appDbID); + } + + // If there's an error, pretend that everything went OK. + + if (err) + { + PUT_RESULT_VAL (Err, errNone); + return kSkipROM; + } + + // Otherwise, substitute the new cardNo and dbID for the + // ones on the stack. + + sub.SetParamVal ("cardNo", appCardNo); + sub.SetParamVal ("dbID", appDbID); + } + + // Could not get information on the specified database. + // Pass it off to the ROM as normal. + } + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::SysBinarySearch + * + * DESCRIPTION: There's a bug in pre-3.0 versions of SysBinarySearch + * that cause it to call the user callback function with a + * pointer just past the array to search. Make a note of + * when we enter SysBinarySearch so that we can make + * allowances for that in MetaMemory's memory checking. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::SysBinarySearch (void) +{ + EmPatchState::EnterSysBinarySearch (); + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::SysEvGroupWait + * + * DESCRIPTION: We patch SysEvGroupWait as the mechanism for feeding + * the Palm OS new events. See comments in + * EmPatchState::PuppetString. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::SysEvGroupWait (void) +{ + // Only do this under 2.0 and later. Under Palm OS 1.0, EvtGetSysEvent + // called SysSemaphoreWait instead. See our headpatch of that function + // for a chunk of pretty similar code. + + if (EmPatchState::OSMajorVersion () == 1) + { + return kExecuteROM; + } + + // Err SysEvGroupWait(UInt32 evID, UInt32 mask, UInt32 value, Int32 matchType, + // Int32 timeout) + + CALLED_SETUP ("Err", "UInt32 evID, UInt32 mask, UInt32 value, Int32 matchType," + "Int32 timeout"); + + CALLED_GET_PARAM_VAL (Int32, timeout); + + CallROMType result; + Bool clearTimeout; + + EmPatchMgr::PuppetString (result, clearTimeout); + + // If timeout is infinite, the kernel wants 0. + // If timeout is none, the kernel wants -1. + + if (clearTimeout && timeout == 0) + { + sub.SetParamVal ("timeout", (Int32) -1); + } + + return result; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::SysFatalAlert + * + * DESCRIPTION: Intercept this and show the user a dialog. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::SysFatalAlert (void) +{ + Preference<bool> pref (kPrefKeyInterceptSysFatalAlert); + if (!*pref) + { + // Palm OS will display a dialog with just a Reset button + // in it. So *always* turn off the Gremlin, as the user + // won't be able to select "Continue". + + Hordes::Stop (); + return kExecuteROM; + } + + // UInt16 SysFatalAlert (const Char* msg) + + CALLED_SETUP ("UInt16", "const Char* msg"); + + CALLED_GET_PARAM_STR (Char, msg); + + string msgString; + + if (msg) + { + msgString = string (msg); + } + else + { + msgString = Platform::GetString (kStr_UnknownFatalError); + } + + Errors::ReportErrSysFatalAlert (msgString.c_str ()); + + // On Debug or Reset, an exception will be thrown past this point, + // meaning that we don't have to return fatalEnterDebugger or fatalReset. + // On the psuedo Next Gremlin, Hordes::ErrorEncountered will have been + // called. Otherwise, Continue and Next Gremlin end up coming here, and + // we should return fatalDoNothing. + + PUT_RESULT_VAL (UInt16, fatalDoNothing); + + return kSkipROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::SysLaunchConsole + * + * DESCRIPTION: Stub this function out so that it doesn't do anything. + * We completely handle the console in DebugMgr, so there's + * no need to get the ROM all heated up. Also, there are + * problems with actually letting the ROM try to launch its + * console task, at least on the Mac. It will try to open + * a serial port socket and do stuff with it. That attempt + * will fail, as much of the serial port processing on the + * Mac is handled at idle time, and idle time processing is + * inhibited when handling debugger packets + * (SysLaunchConsole is usually called by a debugger via + * the RPC packet). Since serial port processing doesn't + * occur, SysLaunchConsole hangs. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::SysLaunchConsole (void) +{ + // Err SysLaunchConsole(void) + + CALLED_SETUP ("Err", "void"); + + PUT_RESULT_VAL (Err, errNone); + + return kSkipROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::SysSemaphoreWait + * + * DESCRIPTION: We patch SysSemaphoreWait as the mechanism for feeding + * the Palm OS new events. See comments in + * EmPatchState::PuppetString. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::SysSemaphoreWait (void) +{ + // Only do this under 1.0. Under Palm OS 2.0 and later, EvtGetSysEvent + // calls SysEvGroupWait instead. See our headpatch of that function + // for a chunk of pretty similar code. + + if (EmPatchState::OSMajorVersion () != 1) + { + return kExecuteROM; + } + + // Err SysSemaphoreWait(UInt32 smID, UInt32 priority, Int32 timeout) + + CALLED_SETUP ("Err", "UInt32 smID, UInt32 priority, Int32 timeout"); + + CALLED_GET_PARAM_VAL (Int32, timeout); + + CallROMType result; + Bool clearTimeout; + + EmPatchMgr::PuppetString (result, clearTimeout); + + // If timeout is infinite, the kernel wants 0. + // If timeout is none, the kernel wants -1. + + if (clearTimeout && timeout == 0) + { + sub.SetParamVal ("timeout", (Int32) -1); + } + + return result; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::SysUIAppSwitch + * + * DESCRIPTION: SysUIAppSwitch is called from the following locations + * for the given reasons. When running Gremlins, we want + * to prevent SysUIAppSwitch from doing its job, which is + * to record information about the application to switch + * to and to then post an appStopEvent to the current + * application. + * + * There are a couple of places where SysUIAppSwitch is + * called to quit and re-run the current application. + * Therefore, we want to stub out SysUIAppSwitch only when + * the application being switched to is not the currently + * running application. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +// Places where this is called: +// +// - LauncherMain.c (AppsViewSwitchApp) to launch new app. +// - PrefApp (PilotMain) to launch a panel. +// - SyncApp (prvLaunchExternalModule) to launch a "service owner" +// - AppLaunchCmd.h (AppLaunchWithCommand) ??? +// - ModemPanel.h (ModemPanelLaunch) ??? +// - callApp.h (LaunchApp) ??? +// - ExgMgr.c (ExgNotifyReceive) to send a sysAppLaunchCmdGoTo message. +// - GraffitiGlue.c (PrvLaunchGraffitiDemo) to launch Graffiti demo. +// - Keyboard.c (PrvLaunchGraffitiDemo) to launch Graffiti demo. +// - Launcher.c (LauncherFormHandleEvent) handles taps on launcher icons. +// - SystemMgr.c (SysHandleEvent) to send sysAppLaunchCmdSystemLock +// in response to seeing a lockChr keyboard message. +// - SystemMgr.c (SysHandleEvent) to switch apps in response to hard#Chr +// keyboard messages. +// - Find.c (Find) to send sysAppLaunchCmdGoTo message. +// +// - ButtonsPanel.c (ButtonsFormHandleEvent) switch to another panel. +// - FormatsPanel.c (FormatsFormHandleEvent) switch to another panel. +// - GeneralPanel.c (GeneralFormHandleEvent) switch to another panel. +// - ModemPanel.c (ModemFormHandleEvent) switch to another panel. +// - NetworkPanel.c (NetworkFormHandleEvent) switch to another panel. +// - OwnerPanel.c (OwnerViewHandleEvent) switch to another panel. +// - ShortCutsPanel.c (ShortCutFormHandleEvent) switch to another panel. + +CallROMType SysHeadpatch::SysUIAppSwitch (void) +{ + // Err SysUIAppSwitch(UInt16 cardNo, LocalID dbID, UInt16 cmd, MemPtr cmdPBP) + + CALLED_SETUP ("Err", "UInt16 cardNo, LocalID dbID, UInt16 cmd, MemPtr cmdPBP"); + + CALLED_GET_PARAM_VAL (UInt16, cardNo); + CALLED_GET_PARAM_VAL (LocalID, dbID); + CALLED_GET_PARAM_VAL (MemPtr, cmdPBP); + + if (false /*LogLaunchCodes ()*/) + { + char name[dmDBNameLength] = {0}; + UInt32 type = 0; + UInt32 creator = 0; + + /* Err err =*/ ::DmDatabaseInfo ( + cardNo, dbID, name, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + &type, &creator); + + LogAppendMsg ("SysUIAppSwitch called:"); + LogAppendMsg (" cardNo: %ld", (long) cardNo); + LogAppendMsg (" dbID: 0x%08lX", (long) dbID); + LogAppendMsg (" name: %s", name); + LogAppendMsg (" type: %04lX", type); + LogAppendMsg (" creator: %04lX", creator); + } + + // We are headpatching SysUIAppSwitch; if we skip the ROM version, we + // need to replicate at least this part of its functionality: + // + // If the last launch attempt failed, release the command parameter block, if + // any. When a launch succeeds, the UIAppShell will clear this global + // and free the chunk itself when the app quits. + { + CEnableFullAccess munge; // Remove blocks on memory access. + emuptr nextUIAppCmdPBP = EmLowMem_GetGlobal (nextUIAppCmdPBP); + if (nextUIAppCmdPBP) + { + MemPtrFree((MemPtr) nextUIAppCmdPBP); + EmLowMem_SetGlobal (nextUIAppCmdPBP, 0); + } + } + + // Get the current application card and db. If we are attempting to switch + // to the same app, allow it. + + UInt16 currentCardNo; + LocalID currentDbID; + Err err = SysCurAppDatabase (¤tCardNo, ¤tDbID); + + // Got an error? Give up and let default handling occur. + + if (err != 0) + return kExecuteROM; + + // Switching to current app; let default handling occur. + + if ((cardNo == currentCardNo) && (dbID == currentDbID)) + return kExecuteROM; + + // OK, we're switching to a different application. If Gremlins is running + // and we're trying to switch to an application that's not on its list, + // then stub out SysUIAppSwitch to do nothing. + + if ((Hordes::IsOn () || EmEventPlayback::ReplayingEvents ()) && + !Hordes::CanSwitchToApp (cardNo, dbID)) + { + // Store the incoming parameter block in nextUIAppCmdPBP, just + // like the real version would. This way, it will get cleaned + // up by the code above, or by the return code in UIAppShell, or + // by the real SysUIAppSwitch, or whatever. By not freeing it + // now, we preserve compatibility with any application that + // expects the block to stay around for a while. + + // CEnableFullAccess munge; // Remove blocks on memory access. + // EmLowMem_SetGlobal (nextUIAppCmdPBP, (MemPtr) cmdPBP); + + // Actually, let's not take that approach. It looks to me that + // it could lead to problems in UIAppShell. When SysAppLaunch + // returns, UIAppShell will try to free the block that previously + // was in nextUIAppCmdPBP, which it had saved in a local variable. + // So let's examing the following: UIAppShell launches an application, + // saving the parameter block. The next application tries calling + // SysUIAppSwitch with a parameter block. We save that parameter + // block in nextUIAppCmdPBP and then keep the application running. + // Then the application decides to quit for whatever reason. + // UIAppShell will free any parameter it originally used to free + // the application. It then notices that the application just up + // and quit, and so tries launching some default application (usually + // the previous application). However, in doing so, one of two + // things can happen. (1) nextUIAppCmdPBP is set to NULL by UIAppShell + // without first deleting any contents. (2) The next application + // is launched with its parameter block set to whatever is left over + // in nextUIAppCmdPBP, which is now the parameter block to the application + // we earlier prevented from running. + // + // Neither of those is correct, so let's see if we can just dump + // the block now, and hope that no applications complain. + + MemPtr p = (MemPtr) cmdPBP; + if (p) + { + MemPtrFree (p); + } + + PUT_RESULT_VAL (Err, errNone); + return kSkipROM; + } + + // Do the normal app switch. + + return kExecuteROM; +} + + +/*********************************************************************** + * + * FUNCTION: SysHeadpatch::TblHandleEvent + * + * DESCRIPTION: See comments in SysTailpatch::TblHandleEvent. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +CallROMType SysHeadpatch::TblHandleEvent (void) +{ + if (EmPatchState::HasSelectItemBug ()) + { + gSaveDrawStateStackLevel = ::PrvGetDrawStateStackLevel (); + } + + return kExecuteROM; +} + + +#pragma mark - + +// =========================================================================== +// ¥ SysTailpatch +// =========================================================================== + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::MarkUIObjects + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::MarkUIObjects (void) +{ + MetaMemory::MarkUIObjects (); +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::BmpCreate + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::BmpCreate (void) +{ + // BitmapType *BmpCreate (Coord width, Coord height, UInt8 depth, + // ColorTableType *colortableP, UInt16 *error) + + CALLED_SETUP ("BitmapType*", "Coord width, Coord height, UInt8 depth" + "ColorTableType *colortableP, UInt16 *error"); + + GET_RESULT_PTR (); + + MetaMemory::RegisterBitmapPointer ((MemPtr) result); +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::BmpDelete + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::BmpDelete (void) +{ + // Err BmpDelete (BitmapType *bitmapP) + + CALLED_SETUP ("Err", "BitmapType *bitmapP"); + + CALLED_GET_PARAM_VAL (MemPtr, bitmapP); + + MetaMemory::UnregisterBitmapPointer (bitmapP); +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::ClipboardAddItem + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::ClipboardAddItem (void) +{ + if (!Hordes::IsOn () && !gDontPatchClipboardAddItem) + { + ::PrvCopyPalmClipboardToHost (); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::ClipboardAppendItem + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::ClipboardAppendItem (void) +{ + if (!Hordes::IsOn () && !gDontPatchClipboardAddItem) + { + ::PrvCopyPalmClipboardToHost (); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::DmGet1Resource + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::DmGet1Resource (void) +{ + // MemHandle DmGet1Resource (DmResType type, DmResID id) + + CALLED_SETUP ("MemHandle", "DmResType type, DmResID id"); + + CALLED_GET_PARAM_VAL (DmResType, type); +// CALLED_GET_PARAM_VAL (DmResID, id); + +#define iconType 'tAIB' +#define bitmapRsc 'Tbmp' + + if (type == iconType || type == bitmapRsc) + { + GET_RESULT_PTR (); + MetaMemory::RegisterBitmapHandle ((MemHandle) result); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::DmGetResource + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::DmGetResource (void) +{ + // MemHandle DmGetResource (DmResType type, DmResID id) + + CALLED_SETUP ("MemHandle", "DmResType type, DmResID id"); + + CALLED_GET_PARAM_VAL (DmResType, type); +// CALLED_GET_PARAM_VAL (DmResID, id); + + if (type == iconType || type == bitmapRsc) + { + GET_RESULT_PTR (); + MetaMemory::RegisterBitmapHandle ((MemHandle) result); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::EvtGetEvent + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::EvtGetEvent (void) +{ + // void EvtGetEvent(const EventPtr eventP, Int32 timeout); + + CALLED_SETUP ("void", "const EventPtr eventP, Int32 timeout"); + + CALLED_GET_PARAM_REF (EventType, eventP, Marshal::kInput); + CALLED_GET_PARAM_VAL (Int32, timeout); + + LogEvtGetEvent (*eventP, timeout); + + EmPatchState::SetEvtGetEventCalled (true); +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::EvtGetPen + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::EvtGetPen (void) +{ + // void EvtGetPen(Int16 *pScreenX, Int16 *pScreenY, Boolean *pPenDown) + + CALLED_SETUP ("void", "Int16 *pScreenX, Int16 *pScreenY, Boolean *pPenDown"); + + CALLED_GET_PARAM_REF (Int16, pScreenX, Marshal::kInput); + CALLED_GET_PARAM_REF (Int16, pScreenY, Marshal::kInput); + CALLED_GET_PARAM_REF (Boolean, pPenDown, Marshal::kInput); + + LogEvtGetPen (*pScreenX, *pScreenY, *pPenDown); +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::EvtGetSysEvent + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::EvtGetSysEvent (void) +{ + // void EvtGetSysEvent(EventPtr eventP, Int32 timeout) + + CALLED_SETUP ("void", "EventPtr eventP, Int32 timeout"); + + CALLED_GET_PARAM_REF (EventType, eventP, Marshal::kInput); + CALLED_GET_PARAM_VAL (Int32, timeout); + + LogEvtGetSysEvent (*eventP, timeout); +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::EvtSysEventAvail + * + * DESCRIPTION: If there are no pending events in the real system, + * check to see if we have any pen events to insert. + * Set the function's return value to TRUE if so. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::EvtSysEventAvail (void) +{ + // Boolean EvtSysEventAvail(Boolean ignorePenUps) + + CALLED_SETUP ("Boolean", "Boolean ignorePenUps"); + + CALLED_GET_PARAM_VAL (Boolean, ignorePenUps); + GET_RESULT_VAL (Boolean); + + if (result == 0) + { + EmAssert (gSession); + if (gSession->HasPenEvent ()) + { + EmPenEvent event = gSession->PeekPenEvent (); + + if (event.fPenIsDown || !ignorePenUps) + { + PUT_RESULT_VAL (Boolean, true); + } + } + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::ExgReceive + * + * DESCRIPTION: Log Exchange Manager data. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::ExgReceive (void) +{ + // UInt32 ExgReceive (ExgSocketPtr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP) + + CALLED_SETUP ("UInt32", "ExgSocketPtr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP"); + + CALLED_GET_PARAM_VAL (UInt32, bufLen); + CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kInput); + CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput); + GET_RESULT_VAL (UInt32); + + if (LogExgMgr ()) + { + LogAppendMsg ("ExgMgr: received %ld bytes, err = 0x%04X.", result, *errP); + } + else if (LogExgMgrData ()) + { + LogAppendData ((void*) bufP, bufLen, "ExgMgr: received %ld bytes, err = 0x%04X.", result, *errP); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::ExgSend + * + * DESCRIPTION: Log Exchange Manager data. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::ExgSend (void) +{ + // UInt32 ExgSend (ExgSocketPtr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP) = 0; + + CALLED_SETUP ("UInt32", "ExgSocketPtr exgSocketP, void* bufP, const UInt32 bufLen, Err* errP"); + + CALLED_GET_PARAM_VAL (UInt32, bufLen); + CALLED_GET_PARAM_PTR (void, bufP, bufLen, Marshal::kInput); + CALLED_GET_PARAM_REF (Err, errP, Marshal::kInput); + GET_RESULT_VAL (UInt32); + + if (LogExgMgr ()) + { + LogAppendMsg ("ExgMgr: sent %ld bytes, err = 0x%04X.", result, *errP); + } + else if (LogExgMgrData ()) + { + LogAppendData ((void*) bufP, bufLen, "ExgMgr: sent %ld bytes, err = 0x%04X.", result, *errP); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::FtrInit + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::FtrInit (void) +{ + // void FtrInit(void) + + // Get information about the current OS so that we know + // what features are implemented (for those cases when we + // can't make other tests, like above where we test for + // the existance of a trap before calling it). + + // Read the version into a local variable; the ROM Stub facility + // automatically maps local variables into Palm space so that ROM + // functions can get to them. If we were to pass &gOSVersion, + // the DummyBank functions would complain about an invalid address. + + UInt32 value; + Err err = ::FtrGet (sysFtrCreator, sysFtrNumROMVersion, &value); + + if (err == errNone) + { + EmPatchState::SetOSVersion(value); + } + else + { + EmPatchState::SetOSVersion(kOSUndeterminedVersion); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::FtrSet + * + * DESCRIPTION: Look for calls indicating that we're running a + * non-Roman system + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::FtrSet (void) +{ + // Err FtrSet (UInt32 creator, UInt16 featureNum, UInt32 newValue) + + CALLED_SETUP ("Err", "UInt32 creator, UInt16 featureNum, UInt32 newValue"); + + CALLED_GET_PARAM_VAL (UInt32, creator); + CALLED_GET_PARAM_VAL (UInt16, featureNum); + CALLED_GET_PARAM_VAL (UInt32, newValue); + GET_RESULT_VAL (Err); + + // Look for calls indicating that we're running a non-Roman system. + + if (result == errNone) + { + if (creator == sysFtrCreator && featureNum == sysFtrNumEncoding) + { + EmPatchState::SetEncoding (newValue); + } + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::HwrMemReadable + * + * DESCRIPTION: Patch this function so that it returns non-zero if the + * address is in the range of memory that we've mapped in + * to emulated space. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::HwrMemReadable (void) +{ + // UInt32 HwrMemReadable(MemPtr address) + + CALLED_SETUP ("UInt32", "MemPtr address"); + + CALLED_GET_PARAM_VAL (emuptr, address); + GET_RESULT_VAL (UInt32); + + if (result == 0) + { + void* addrStart; + uint32 addrLen; + + Memory::GetMappingInfo (address, &addrStart, &addrLen); + + PUT_RESULT_VAL (UInt32, addrLen); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::HwrSleep + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::HwrSleep (void) +{ + // void HwrSleep(Boolean untilReset, Boolean emergency) + + MetaMemory::MarkLowMemory (offsetof (M68KExcTableType, busErr), + offsetof (M68KExcTableType, busErr) + sizeof (emuptr)); + + MetaMemory::MarkLowMemory (offsetof (M68KExcTableType, addressErr), + offsetof (M68KExcTableType, addressErr) + sizeof (emuptr)); + + MetaMemory::MarkLowMemory (offsetof (M68KExcTableType, illegalInstr), + offsetof (M68KExcTableType, illegalInstr) + sizeof (emuptr)); + + MetaMemory::MarkLowMemory (offsetof (M68KExcTableType, autoVec1), + offsetof (M68KExcTableType, trapN[0])); + + // On Palm OS 1.0, there was code in HwrSleep that would execute only if + // memory location 0xC2 was set. It looks like debugging code (that is, + // Ron could change it from the debugger to try different things out), + // but we still have to allow access to it. + + if (EmPatchState::OSMajorVersion () == 1) + { + MetaMemory::MarkLowMemory (0x00C2, 0x00C3); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::SysAppStartup + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::SysAppStartup (void) +{ + // Err SysAppStartup(SysAppInfoPtr* appInfoPP, MemPtr* prevGlobalsP, MemPtr* globalsPtrP) + + CALLED_SETUP ("Err", "SysAppInfoPtr* appInfoPP, MemPtr* prevGlobalsP, MemPtr* globalsPtrP"); + + CALLED_GET_PARAM_REF (SysAppInfoPtr, appInfoPP, Marshal::kInput); + GET_RESULT_VAL (Err); + + if (result != errNone) + return; + + if (appInfoPP == EmMemNULL) + return; + + emuptr appInfoP = EmMemGet32 (appInfoPP); + if (!appInfoP) + return; + + if (false /*LogLaunchCodes ()*/) + { + emuptr dbP = EmMemGet32 (appInfoP + offsetof (SysAppInfoType, dbP)); + emuptr openP = EmMemGet32 (dbP + offsetof (DmAccessType, openP)); + LocalID dbID = EmMemGet32 (openP + offsetof (DmOpenInfoType, hdrID)); + UInt16 cardNo = EmMemGet16 (openP + offsetof (DmOpenInfoType, cardNo)); + + char name[dmDBNameLength] = {0}; + UInt32 type = 0; + UInt32 creator = 0; + + /* Err err =*/ ::DmDatabaseInfo ( + cardNo, dbID, name, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + &type, &creator); + + LogAppendMsg ("SysAppStartup called:"); + LogAppendMsg (" cardNo: %ld", (long) cardNo); + LogAppendMsg (" dbID: 0x%08lX", (long) dbID); + LogAppendMsg (" name: %s", name); + LogAppendMsg (" type: %04lX", type); + LogAppendMsg (" creator: %04lX", creator); + } + + Int16 cmd = EmMemGet16 (appInfoP + offsetof (SysAppInfoType, cmd)); + + EmuAppInfo newAppInfo; + EmPatchState::CollectCurrentAppInfo (appInfoP, newAppInfo); + + newAppInfo.fCmd = cmd; + EmPatchState::AddAppInfo(newAppInfo); + + if (cmd == sysAppLaunchCmdNormalLaunch) + { + // Clear the flags that tell us which warnings we've already issued. + // We reset these flags any time a new application is launched. + // + // !!! Put these flags into EmuAppInfo? That way, we can keep + // separate sets for sub-launched applications. + +// Errors::ClearWarningFlags (); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::SysBinarySearch + * + * DESCRIPTION: There's a bug in pre-3.0 versions of SysBinarySearch + * that cause it to call the user callback function with a + * pointer just past the array to search. Make a note of + * when we enter SysBinarySearch so that we can make + * allowances for that in MetaMemory's memory checking. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::SysBinarySearch (void) +{ + EmPatchState::ExitSysBinarySearch (); +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::SysTaskCreate + * + * DESCRIPTION: Track calls to SysTaskCreate to get information on any + * stacks created. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::SysTaskCreate (void) +{ + // Err SysTaskCreate(UInt32 * taskIDP, UInt32 * creator, ProcPtr codeP, + // MemPtr stackP, UInt32 stackSize, UInt32 attr, UInt32 priority, + // UInt32 tSlice) + + CALLED_SETUP ("Err", "UInt32 * taskIDP, UInt32 * creator, ProcPtr codeP," + "MemPtr stackP, UInt32 stackSize, UInt32 attr, UInt32 priority," + "UInt32 tSlice"); + + CALLED_GET_PARAM_VAL (emuptr, stackP); + CALLED_GET_PARAM_VAL (UInt32, stackSize); + GET_RESULT_VAL (Err); + + if (result == errNone) + { + StackRange range (stackP, stackP + stackSize); + EmPalmOS::RememberStackRange (range); + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::TblHandleEvent + * + * DESCRIPTION: There's a bug in a private Table Manager function called + * SelectItem (that's the name of the function, not the + * bug). Under certain circumstances, the function will + * exit early without popping the draw state that it pushed + * onto the stack at the start of the function. This + * tailpatch remedies that problem. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::TblHandleEvent (void) +{ + if (EmPatchState::HasSelectItemBug ()) + { + long curDrawStateStackLevel = ::PrvGetDrawStateStackLevel (); + long levelDelta = curDrawStateStackLevel - gSaveDrawStateStackLevel; + + if (levelDelta == 1) + { + WinPopDrawState (); + } + } +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::TimInit + * + * DESCRIPTION: TimInit is where a special boolean is set to trigger a + * bunch of RTC bug workarounds in the ROM (that is, there + * are RTC bugs in the Dragonball that the ROM needs to + * workaround). We're not emulating those bugs, so turn + * off that boolean. Otherwise, we'd have to add support + * for the 1-second, 1-minute, and 1-day RTC interrupts in + * order to get those workarounds to work. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::TimInit (void) +{ + // Err TimInit(void) + + // Turn off the RTC bug workaround flag. + + CEnableFullAccess munge; + + emuptr timGlobalsP = EmLowMem_GetGlobal (timGlobalsP); + EmAliasTimGlobalsType<PAS> timGlobals (timGlobalsP); + + if (timGlobals.rtcBugWorkaround == 0x01) + { + timGlobals.rtcBugWorkaround = 0; + } + + // Set the current date. + + ::PrvSetCurrentDate (); +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::UIInitialize + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::UIInitialize (void) +{ + // Void UIInitialize (void) + + EmPatchState::SetUIInitialized (true); + + // Reconfirm the strict intl checks setting, whether on or off. + + Preference<Bool> intlPref (kPrefKeyReportStrictIntlChecks); + + if (EmPatchMgr::IntlMgrAvailable ()) + { + ::IntlSetStrictChecks (*intlPref); + } + + // Reconfirm the overlay checks setting, whether on or off. + + Preference<Bool> overlayPref (kPrefKeyReportOverlayErrors); + (void) ::FtrSet (omFtrCreator, omFtrShowErrorsFlag, *overlayPref); + + // Prevent the device from going to sleep. + + ::SysSetAutoOffTime (0); + + // Can't call PrefSetPreference on 1.0 devices.... + + if (EmLowMem::TrapExists (sysTrapPrefSetPreference)) + { + ::PrefSetPreference (prefAutoOffDuration, 0); + } + + // Install a 'pose' feature so that people can tell if they're running + // under the emulator or not. We *had* added a HostControl function + // for this, but people can call that only under Poser or under 3.0 + // and later ROMs. Which means that there's no way to tell under 2.0 + // and earlier ROMs when running on an actual device. + // + // Note that we do this here instead of in a tailpatch to FtrInit because + // of a goofy inter-dependency. FtrInit is called early in the boot process + // before a valid stack has been allocated and switched to. During this time, + // the ROM is using a range of memory that happens to reside in a free + // memory chunk. Routines in MetaMemory know about this and allow the use + // of this unallocate range of memory. However, in order to work, they need + // to know the current stack pointer value. If we were to call FtrSet from + // the FtrInit tailpatch, the stack pointer will point to the stack set up + // by the ATrap object, not the faux stack in use at the time of FtrInit. + // Thus, the MetaMemory routines get confused and end up getting in a state + // where accesses to the temporary OS stack are flagged as invalid. Hence, + // we defer adding these Features until much later in the boot process (here). + + ::FtrSet ('pose', 0, 0); + + // If we're listening on a socket, install the 'gdbS' feature. The + // existance of this feature causes programs written with the prc tools + // to enter the debugger when they're launched. + + if (Debug::ConnectedToTCPDebugger ()) + { + ::FtrSet ('gdbS', 0, 0x12BEEF34); + } + + // Install the HotSync user-name. + + Preference<string> userName (kPrefKeyUserName); + ::SetHotSyncUserName (userName->c_str ()); + + // Auto-load any files in the Autoload[Foo] directories. + + ::PrvAutoload (); + + // Install our ExgMgr driver + + // Don't do this for now. We don't currently use it, and people get + // confused seeing it show up in application lists, etc. + +// EmFileImport::InstallExgMgrLib (); +} + + +/*********************************************************************** + * + * FUNCTION: SysTailpatch::UIReset + * + * DESCRIPTION: + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void SysTailpatch::UIReset (void) +{ + // Void UIReset (void) + + EmPatchState::SetUIReset (true); +} + + +#pragma mark - + + +/*********************************************************************** + * + * FUNCTION: PrvAutoload + * + * DESCRIPTION: Install the files in the various Autoload directories. + * If there are any designated to be run, pick on to run. + * If the emulator should exit when the picked application + * quits, schedule it to do so. + * + * PARAMETERS: none + * + * RETURNED: nothing + * + ***********************************************************************/ + +void PrvAutoload (void) +{ + // Load all the files in one blow. + + EmFileRefList fileList; + Startup::GetAutoLoads (fileList); + + vector<LocalID> idList; + EmFileImport::LoadPalmFileList (fileList, kMethodHomebrew, idList); + + // Get the application to switch to (if any); + + string appToRun = Startup::GetAutoRunApp (); + + if (!appToRun.empty()) + { + char name[dmDBNameLength]; + strcpy (name, appToRun.c_str()); + + UInt16 cardNo = 0; + LocalID dbID = ::DmFindDatabase (cardNo, name); + + if (dbID != 0) + { + EmPatchState::SetSwitchApp (cardNo, dbID); + + // If we're supposed to quit after running this application, + // start that process in motion. + + if (Startup::QuitOnExit ()) + { + EmPatchState::SetQuitApp (cardNo, dbID); + } + } + } +} + + +/*********************************************************************** + * + * FUNCTION: PrvSetCurrentDate + * + * DESCRIPTION: . + * + * PARAMETERS: None. + * + * RETURNED: Nothing. + * + ***********************************************************************/ + +void PrvSetCurrentDate (void) +{ + CEnableFullAccess munge; + + // Get the current date. + + long year, month, day; + ::GetHostDate (&year, &month, &day); + + // Convert it to days -- and then hourse -- since 1/1/1904 + + UInt32 rtcHours = ::DateToDays (year, month, day) * 24; + + // Update the "hours adjustment" value to contain the current date. + + emuptr timGlobalsP = EmLowMem_GetGlobal (timGlobalsP); + EmAliasTimGlobalsType<PAS> timGlobals (timGlobalsP); + + timGlobals.rtcHours = rtcHours; +} + + +/*********************************************************************** + * + * FUNCTION: PrvGetDrawStateStackLevel + * + * DESCRIPTION: . + * + * PARAMETERS: None. + * + * RETURNED: Nothing. + * + ***********************************************************************/ + +long PrvGetDrawStateStackLevel (void) +{ + CEnableFullAccess munge; + UInt16 level = EmLowMem_GetGlobal (uiGlobals.gStateV3.drawStateIndex); + return level; +} + + +/*********************************************************************** + * + * FUNCTION: PrvCopyPalmClipboardToHost + * + * DESCRIPTION: . + * + * PARAMETERS: None. + * + * RETURNED: Nothing. + * + ***********************************************************************/ + +void PrvCopyPalmClipboardToHost (void) +{ + gDontPatchClipboardGetItem = true; + + UInt16 length; + MemHandle dataHdl = ::ClipboardGetItem (clipboardText, &length); + + gDontPatchClipboardGetItem = false; + + if (length > 0) + { + MemPtr dataPtr = ::MemHandleLock (dataHdl); + if (dataPtr) + { + void* dataCopy = Platform::AllocateMemory (length); + if (dataCopy) + { + EmMem_memcpy (dataCopy, (emuptr) dataPtr, length); + + ByteList palmChars; + ByteList hostChars; + char* charData = (char*) dataCopy; + + copy (charData, charData + length, back_inserter (palmChars)); + + Platform::CopyToClipboard (palmChars, hostChars); + Platform::DisposeMemory (dataCopy); + } + + ::MemHandleUnlock (dataHdl); + } + } + else + { + ByteList palmChars; + ByteList hostChars; + + Platform::CopyToClipboard (palmChars, hostChars); + } +} + + +/*********************************************************************** + * + * FUNCTION: PrvCopyHostClipboardToPalm + * + * DESCRIPTION: . + * + * PARAMETERS: None. + * + * RETURNED: Nothing. + * + ***********************************************************************/ + +void PrvCopyHostClipboardToPalm (void) +{ + ByteList palmChars; + ByteList hostChars; + + Platform::CopyFromClipboard (palmChars, hostChars); + + gDontPatchClipboardAddItem = true; + + if (palmChars.size () > 0) + { + // Limit us to cbdMaxTextLength characters so as to not + // overburden the dynamic heap. This is the same limit used by + // the Field Manager does when calling ClipboardAddItem (except + // that the Field Manager puts up a dialog saying that it won't + // copy the text to the clipboard instead of truncating). + + if (palmChars.size () > cbdMaxTextLength) + { + palmChars.resize (cbdMaxTextLength); + } + + // Set the Palm OS clipboard to the text data. + + ::ClipboardAddItem (clipboardText, &palmChars[0], palmChars.size ()); + } + else + { + ::ClipboardAddItem (clipboardText, NULL, 0); + } + + gDontPatchClipboardAddItem = false; +} |